WordPress的自定义元框和字段:更改基于用户编辑页面的目录上传

时间:2014-08-08 作者:Emanuele Feliziani

我已经在StackOverflow上发布了这篇文章,但我意识到最好还是在这里发布。

我正在使用CMB script (Custom Meta Boxes and Fields for WordPress) 用于为具有自定义角色的不同用户上载文件cliente.

我能够显示字段并使其工作(尽管它们仅在编辑用户时显示,而不是在创建用户时显示,但这是另一个问题)。我现在试图实现的是为不同的用户将文件上载到不同的文件夹。

代码如下:

// Here we add a new user role, "cliente"
add_role( \'cliente\', \'Cliente\' );

add_filter(\'wp_handle_upload_prefilter\', \'my_upload_prefilter\');
add_filter(\'wp_handle_upload\', \'my_upload_postfilter\');

function my_upload_prefilter( $file ) {
    add_filter(\'upload_dir\', \'custom_upload_dir\');
    return $file;
}

function my_upload_postfilter( $fileinfo ) {
    remove_filter(\'upload_dir\', \'custom_upload_dir\');
    return $fileinfo;
}

function custom_upload_dir( $path ) {
    global $pagenow;

    // Check if we are on the user-edit.php page
    if ( $pagenow == \'user-edit.php\' && isset($_GET[\'user_id\']) ) {
        // Set the role we want to change the path for
        $role_to_check = \'cliente\';
        // Get a bunch of user info for later use
        $user_id = filter_var( $_GET[\'user_id\'], FILTER_SANITIZE_NUMBER_INT );
        $meta = get_user_meta($user_id);
        $roles = unserialize($meta[\'wp_capabilities\'][0]);
        // If we are on the chosen role page, set the $customdir to first_name + last_name
        if ( !empty($roles[$role_to_check]) ) {
            $customdir = \'/\' . $meta[\'first_name\'][0] . $meta[\'last_name\'][0];
        }
    } else {
        // Here we are not on the user-edit.php page. This is just a check to prove that WP is not recognizing the correct page, maybe because we are doing an Ajax call when this function is called. Confusing.
        $customdir = \'/did-not-work\';
    }

    // If there is any error, just return the $path and abort the rest.
    if ( !empty( $path[\'error\'] ) ) {
        return $path;
    }

    // Here we set the new $path with the $customdir set above
    $path[\'path\']    = str_replace($path[\'subdir\'], \'\', $path[\'path\']); //remove default subdir (year/month)
    $path[\'url\']     = str_replace($path[\'subdir\'], \'\', $path[\'url\']);      
    $path[\'subdir\']  = $customdir;
    $path[\'path\']   .= $customdir; 
    $path[\'url\']    .= $customdir; 
    return $path;

}
从我运行的一些检查来看,我的代码似乎确实检索到了用户id和数据库中存储的数据,但在上载图像时没有检测到它。这可能与我们通过Ajax或类似的方式上传图像有关吗?

我不想基于当前登录的用户进行上传,但作为超级管理员,我正在使用编辑用户对用户进行编辑。php页面。

任何帮助都将不胜感激。

1 个回复
最合适的回答,由SO网友:Emanuele Feliziani 整理而成

我自己想出来的,所以我会把答案贴在这里,请注意,原来的答案也可以找到on StackOverflow. 如果mods觉得应该从这里删除并只保留,请继续。我想这两个地方都可能有用。

首先是正确的代码,然后是解释:

// Here we add a new user role, "cliente".
add_role( \'cliente\', \'Cliente\' );

// These are the filters we need to add in order to modify the default upload path.
add_filter(\'wp_handle_upload_prefilter\', \'my_upload_prefilter\');
add_filter(\'wp_handle_upload\', \'my_upload_postfilter\');

function my_upload_prefilter( $file ) {
    add_filter(\'upload_dir\', \'custom_upload_dir\');
    return $file;
}
function my_upload_postfilter( $fileinfo ) {
    remove_filter(\'upload_dir\', \'custom_upload_dir\');
    return $fileinfo;
}

function custom_upload_dir( $path ) {
    // When uploading, the file gets sent to upload_async.php, so we need to take the referral page in order to be able to get the user_id we need. We then take the query string, pass it through parse_str and store it in a $query_array. Took me a while to figure it out, but now it works like a charm.
    $actual_page = $_SERVER[\'HTTP_REFERER\'];
    parse_str( parse_url($actual_page, PHP_URL_QUERY), $query_array );

    // Check if we are uploading from the user-edit.php page.
    if ( strpos($actual_page, \'user-edit.php\') ) {
        // Set the role we want to change the path for.
        $role_to_check = \'cliente\';
        // Get a bunch of user info for later use
        $user_id = filter_var( $query_array[\'user_id\'], FILTER_SANITIZE_NUMBER_INT );
        $meta = get_user_meta( $user_id );
        $roles = unserialize( $meta[\'wp_capabilities\'][0] );
        // If we are on the chosen role page, set the $customdir to first_name + last_name
        if ( !empty($roles[$role_to_check]) ) {
            $customdir = \'/docs/\' . $meta[\'first_name\'][0] . $meta[\'last_name\'][0];

            // If there is any error, just return the $path and abort the rest.
            if ( !empty( $path[\'error\'] ) ) {
                return $path;
            }

            // Here we set the new $path with the $customdir set above
            $new_subdir = $customdir . $path[\'subdir\'];
            $path[\'path\']    = str_replace( $path[\'subdir\'], $new_subdir, $path[\'path\'] );
            $path[\'url\']     = str_replace( $path[\'subdir\'], $new_subdir, $path[\'url\'] );
            $path[\'subdir\']  = $new_subdir;
            return $path;
        }
    } else {
        // We are not uploading from user-edit.php, so go ahead as per default.
        return $path;
    }
}
问题是,通过Ajax上传时,$pagenow 正确存储async-upload.php 页面,而不是我们所在的url。我只需要通过php检索推荐页面$_SERVER[\'HTTP_REFERER\'] (请注意referer 打字错误的存在是因为http规范中有一个遗留的打字错误,很有趣)。

还请注意,PHP规范不鼓励使用HTTP_REFERER 因为它可能会根据服务器配置产生意外的结果,但在这种情况下,我应该完全控制服务器,所以这应该不是问题。如果您遇到任何问题,我建议您检查一下。

一旦我有了正确的url,我就能够解析它并检查我们是否在user-edit.php, 如果是的话user_id 从查询字符串开始,然后从那里继续。

我花了一段时间才弄明白,但事后看来,这很容易。

希望将来能帮助别人。

结束

相关推荐

WPAlChemy Metabox重写插件

所以我的问题是:我创建了一个名为“项目”的自定义帖子类型。我已经通过WPAlchemy成功添加了几个代谢组。这些很好用。我遇到的问题是,当我为相关项目创建带有复选框的元框时,我可以使用复选框列出所有项目标题,但当我至少选择一个并保存自定义帖子时,它会重写Slug。我想是因为我打电话<?php the_title(); ?>. 下面是我的meta PHP文件代码:<div class=\"my_meta_control\"> <p>Add or subt