2

I've inherited a site built with a theme by Highgrade (southcentral) which is built using the Redux framework.

I'm seeing the following error in the frontend and admin panel:

Warning: Invalid argument supplied for foreach() in /Volumes/Data/Users/me/Sites/reference360.eu/wordpress/wp-content/themes/southcentral/highgrade/framework/inc/fields/typography/field_typography.php on line 772

I've tried altering permissions and ownership on googlefonts.json but to no avail.

The problem seems to be within the Redux framework - see this thread on github

I'm debugging in the typography.php class :

 if (!isset($this->parent->fonts['google']) || empty($this->parent->fonts['google'])) {
            $this->parent->fonts['google'] = json_decode($wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json'), true);
            var_dump(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json');
            var_dump($wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json')); exit;
            $this->parent->font_groups['google'] = array(
                'id'        => 'google',
                'text'      => __('Google Webfonts', 'redux-framework'),
                'children'  => array(),
            );
            foreach ($this->parent->fonts['google'] as $font => $extra) {
                $this->parent->font_groups['google']['children'][] = array(
                    'id'    => $font,
                    'text'  => $font
                );
            }
        }
    }

Anyone got any idea what might be causing this? The file exists and is at the path specified. Development environment is OSX Mavericks.

UPDATE:

changing the ownership of the entire wordpress directory to _www:_www resolves the problem but is obviously not a great solution.

  • Why are you trying to use $wp_filesystem->get_contents here? Just use the normal php file_get_contents instead. – Otto Oct 22 '14 at 17:34
  • I'm not. The author of the theme is. I want to understand the problem not hack around it. – codecowboy Oct 22 '14 at 17:35
  • Well, tell the author that he's doing-it-wrong and switch those to file_get_contents instead. I'll write a more detailed answer here. – Otto Oct 22 '14 at 17:35
  • Otto's answer should be selected as the answer to this question. Although, there is probably further context that could be added on what to do when you can't use file_get_contents() due to WP rules. – Tim Malone Mar 7 '18 at 22:14
2

It is not necessary to use the WP_Filesystem for every little thing, and in this case, the correct solution is to use the normal file_get_contents.

The WP_Filesystem is a wrapper around various ways to interact with the filesystem in a safe manner... but it's not meant for everything.

Fundamentally, the WP_Filesystem code was created to allow WordPress to update itself.

When doing such a thing, file ownership is a rather big deal. A lot of servers run as "www" (for example) instead of as the actual owner of the PHP files. If WordPress were to write a file directly in such a case, the resulting file would be owned by "www" as well, not by the true and correct owner. This can lead to security issues, especially in shared hosting.

So, the WP_Filesystem abstracts the file operations. It can read and write files in ways that will preserve file ownership. If it can write directly and the ownership remains, then it will do so, but if it cannot, then it will instead need credentials for some method like FTP. By using credentials, it can log in via that route and write files using the proper owner of them.

What this means is that before you use the WP_Filesystem, it has to be set up. A test has to be performed, and if the test fails, then credentials must be obtained from the user. Without those credentials, it can't function.

In your case, since "changing the ownership of the entire wordpress directory to _www:_www" fixed the problem, this is what is happening to you. The test of it trying to write a file and getting the proper ownership fails. By changing the owner of the existing files, you're changing the conditions for that test.

Now, the truth is that in this case, there's no reason to use the WP_Filesystem at all. He's reading a file. He can read that file directly. Ownership doesn't matter here. So, really, just use file_get_contents. Using the WP_Filesystem for this makes no sense.

More on the WP_Filesystem, from a how-to-use-it perspective: http://ottopress.com/2011/tutorial-using-the-wp_filesystem/

  • 1
    I find it a little self–contradicting to argue for file_get_contents(), while it is being simultaneously forbidden by repo rules. What if this was public theme in repo? I get that non–repo themes can just (and do, myself included) “screw it” this rule, but I think it's important context for the answer and a in–repo case isn't covered by recommending it. – Rarst Oct 22 '14 at 18:58
  • @Otto so WP Filesystem performs a test to write a file before it does $wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json') in my case? If I knew where it tried to write a file I could just change permissions on that directory so that would be useful information – codecowboy Oct 22 '14 at 19:05
  • Also, all WP_Filesystem_Direct::file_get_contents seems to do is wrap and error suppress php's file_get_contents() – codecowboy Oct 22 '14 at 19:23
  • @codecowboy The global $wp_filesystem variable is not set until you call the WP_Filesystem() function, which actually does that test for each of the assorted methods. If the direct method works, then it gets assigned to that variable. So you can't call $wp_filesystem->get_contents() until you've called WP_Filesystem() once. – Otto Oct 22 '14 at 20:30
  • @Rarst If this was for a theme in the repository, I'd recommend rewriting this entirely so as to not have to read and parse that .json file every time. Instead of leaving it as a json file, you read it once, run it through json_decode, print_r the result, and put that into a PHP file, which you then can simply include to set up whatever variable it contains. Why go to the trouble of reading and parsing a file every time when you can just do it once? – Otto Oct 22 '14 at 20:32
1

@codecowboy, what version of Redux are you using? In the newer versions we don't even use the googlefonts.json like this.

I suggest you simply install Redux Framework from the WordPress plugin repository (http://wordpress.org/plugins/redux-framework/), and this problem will be resolved for you as plugin will override the Redux version embedded within your theme.

  • Thanks for this. I will give that a try as a quick solution which will not break any potential future theme updates. – codecowboy Oct 22 '14 at 18:59
  • redux version seems to be 3.2.8.1 – codecowboy Oct 22 '14 at 19:00
  • We work very hard to make sure updates don't destroy themes and if they do, we put in a shim. We think installing the plugin is your best bet. – Dovy Nov 2 '14 at 15:39
1

After some debugging it appears what is really going on here is that WP_Filesystem tries to open an ftp connection to the temporary file while it is doing its checks:

public function get_contents( $file ) {
        $tempfile = wp_tempnam($file);
        $temp = fopen($tempfile, 'w+');

        if ( ! $temp )
            return false;

        if ( ! @ftp_fget($this->link, $temp, $file, FTP_BINARY ) )
            return false; //false is returned and so I end up with an empty google fonts array

        fseek( $temp, 0 ); // Skip back to the start of the file being written to
        $contents = '';

        while ( ! feof($temp) )
            $contents .= fread($temp, 8192);

        fclose($temp);
        unlink($tempfile);
        return $contents;
    }

On my local OSX machine this fails whereas it passes on the target server. I'm not sure why changing ownership of whole wordpress directory to _www:_www allows this ftp_fget to pass given that it is trying to read a temp file in /var/tmp

-2

For the record, the latest version of Redux no longer uses this particular method for loading google fonts. And second, Otto has a certain dislike for the folks at Redux, so take what he says here with a grain of salt. We see theme check errors CONSTANTLY that say:

WARNING: file_put_contents was found in the file class.redux_filesystem.php File operations should use the WP_Filesystem methods instead of direct PHP filesystem calls.

Really? So, Otto? You're making up standards and guidelines as you go? It makes sense, really, since the entire $wp_filesystem base acts like it was put together piecemeal by kids who had no idea what they were doing. Standards, indeed!

  • I was not directly addressing your theme, just the code given. I don't know anything about your framework, per se. Never looked at it in depth. – Otto Oct 22 '14 at 18:17
  • Also, the use of file_get_contents isn't allowed for themes in the WordPress.org directory mainly because lots of malware uses it. The theme check plugin is specifically geared towards those standards. That said, instead of reading a .json file and decoding it every time, it would make a lot more sense to simply decode it once and include the resulting PHP array in the code directly. – Otto Oct 22 '14 at 18:19
  • No, it isn't my theme, and frankly sir, I don;t believe you about the framework, based on recent events with it. – kprovance Oct 22 '14 at 18:19
  • 2
    Please take this elsewhere. Stack Exchange is not a forum by nature, much less so for interpersonal conflicts. – Rarst Oct 22 '14 at 18:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.