Support

Account

Home Forums General Issues acf/upload_prefilter – for every field on options page

Solved

acf/upload_prefilter – for every field on options page

  • Hi,

    I have created an ACF Options page and I want to change the upload path for every ACF file field to “wp-content/uploads/options” only on that Options page by using acf/upload_prefilter.

    This is my function:

    add_filter('acf/upload_prefilter', function($errors) {
        add_filter('upload_dir', function($uploads) {
            $dir = '/options';
            $uploads['url'] = $uploads['baseurl'] . $dir;
            $uploads['path'] = $uploads['basedir'] . $dir;
            return $uploads;
        });
        return $errors;
    });

    I know that I can use the field’s keys or names in the acf/upload_prefilter and that works, but I have quite a few fields on that page, and I was wondering if there’s a way to target the whole page rather than the individual fields.

    I’ve added my Options page as a sub-menu under “options-general.php” with a slug of “options” so the url is wp-admin/options-general.php?page=options.

    However, wrapping my function around in an if statement like these don’t work:

    if ($pagenow == 'options-general.php') { }

    or

    if (strpos($_SERVER['REQUEST_URI'], 'options-general.php?page=options')) { }

    The function doesn’t take any effect on these pages when wrapped in an if statement like that.

    What am I doing wrong? Any assistance would be much appreciated!

  • You would have to target every acf field and then somehow sort out inside your filter/function when to use the change, but I don’t know if you can sort this out. Uploads are done through AJAX and I do not believe that any information about the options page that’s being viewed is included in the data sent in the AJAX request ($_POST). You may be able to detect if it is an options page, but not a specific options page.

    You could tell what is submitted using something like this

    
    add_filter('acf/upload_prefilter', 'record_submitted_data');
    
    function record_submitted_data($errors) {
      // record $_POST in the error log
      ob_start();
      print_r($_POST);
      error_log(ob_get_clean());
      return $errors;
    }
    

    Then you can upload an image on your options page and then look in your error log to see what you have to work with.

  • Hi John,

    Thanks for your input. Using your method for logging the $_POST data, this is the result:

    Array
    (
        [name] => test.png
        [action] => upload-attachment
        [_wpnonce] => dee97d17e2
        [_acfuploader] => field_5a856f0eb49d7
    )

    So, there’s nothing being sent about the origin page, just the ACF field’s key.

    I guess the only and easiest way is just to create an array of all the fields (potentially only about 10, not that many in my use case). This is how I’ve solved it:

    $fields = array('field_1', 'field_2', 'field_3');
    
    foreach ($fields as $field) {
        add_filter("acf/upload_prefilter/name=$field", function($errors) {
            add_filter('upload_dir', function($uploads) {
                $dir = '/options';
                $uploads['url'] = $uploads['baseurl'] . $dir;
                $uploads['path'] = $uploads['basedir'] . $dir;
                return $uploads;
            });
            return $errors;
        });
    }
  • Usually, when I want to target a lot of fields with the same filter it’s something like

    
    $fields = array(
      'field_123456',
      'field_234567',
      // etc for each field
    );
    foreach ($fields as $field_key) {
      add_filter('acf/upload_prefilter/key='.$key, 'my_upload_prefilter');
    }
    
    function my_upload_prefilter($errors) {
      // filter function code
    }
    

    You probably don’t want to use anonymous functions like your first example. but you probably could.

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.