【问题标题】:Custom Meta Boxes and Fields for WordPress: Change directory upload based on user-edit pageWordPress 的自定义元框和字段:根据用户编辑页面更改目录上传
【发布时间】:2014-08-07 16:14:37
【问题描述】:

我正在使用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 或类似的方式上传图片有关吗?

为了清楚起见,我不希望基于当前登录的用户上传,而是在用户上,作为超级管理员,我正在使用 edit-user.php 页面进行编辑。

任何帮助将不胜感激。

【问题讨论】:

  • 等一下,这是否意味着您正在上传文件(通过 AJAX)时无法检索任何其他信息? (.. 通过另一个 ajax 请求?..)
  • 我不知道。这只是一个猜测。检查页面时会检索数据(我在不同情况下做了几次 var_dumps),但是通过 Ajax 上传时,if ( $pagenow == 'user-edit.php' && isset($_GET['user_id']) ) 语句失败,文件被上传到文件夹/did-not-work
  • 您是否尝试过同时记录(回显)$_GET['user_id'] 和 $pagenow?只是想知道问题是在 GET 请求中还是在 $pagenow 变量中。
  • 是的,我做到了,并且都按预期记录:user-edit.php 和正在编辑的 user_id。但是这些在上传文件时不会被发送,从而导致$customdir 变量被设置为/did-not-work。我想这可能是由于 WordPress 何时以及如何调用钩子,但我不知道如何调试它们。
  • 是的,那么您应该检查为什么没有发送它们。您的上传脚本是从哪里调用的?

标签: php wordpress custom-fields meta-boxes


【解决方案1】:

我自己想通了。首先是正确的代码,然后是解释:

// 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 并从那里继续。

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

希望它在未来对其他人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2011-03-25
    • 2011-02-17
    • 1970-01-01
    • 2018-08-25
    • 2021-07-14
    • 1970-01-01
    相关资源
    最近更新 更多