2

I've created custom elements for WPBakery. In the functions.php file, I currently have the following:

add_action( 'vc_before_init', 'vc_before_init_actions' );

function vc_before_init_actions() {
    require_once('vc_elements/text-image/init.php' );
    require_once('vc_elements/text/init.php' );
}

However, as I build more custom elements, that list will be huge. What I'm looking to do is load all files named init.php in each vc_elements subfolder.

This is my current folder structure:

vc_elements
   text-image
      init.php
   text
      init.php

What's the cleanest way to go about this?

Freddy
  • 683
  • 4
  • 35
  • 114

4 Answers4

1

Perhaps something like this would work, assuming that directory only contains sub-directories with the elements you need.

$dir = 'path/to/vc_elements';

// Scan directory for its contents and put in array.  Remove possiblity of .  or ..
$files = array_diff(scandir($dir), array('..', '.'));

foreach ($files as $file) {

  $name = '/path/to/vc_elements/' . $file . '/init.php';
  include $name;

}
DubVader
  • 1,032
  • 1
  • 6
  • 8
  • 1
    Maybe best to use "include($name)" in this solution instead of "require". Even if 'vc_elements' currently ONLY contains folders and each of those folders ALWAYS contains an init.php a future developer may not notice this restriction and add files to "vc_elements" or subfolders without an "init.php'. If which case there will be spurious "requests" for files resulting in fatal errors (with "require") but not when using "include". – scytale Jul 22 '19 at 11:25
  • True. I agree include would be better. Will adjust. – DubVader Jul 22 '19 at 13:36
1

You need to use RecursiveDirectoryIterator to scan the folder and get all files which are named as init.php. Below is the code you can use

add_action( 'vc_before_init', 'vc_before_init_actions' );

function vc_before_init_actions() {
    $dir = '/full_path_to_vc_elements';
    $files = getFiles($dir, 'init.php');
    foreach( $files as $file) {
        require_once( $file );
    }

}

function getFiles($dir, $match) {
    $return = array();
    $iti = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
    foreach($iti as $file){
         if ($file->isDir()) {
            continue;
         }
         if(strpos($file , $match) !== false){
            $return[] = $file->getPathname();
         }
    }
    return $return;
}

So in future if you add any init.php file inside the folder, it will automatically be picked by getFiles() and included using require.

ascsoftw
  • 3,466
  • 2
  • 15
  • 23
1

What I'm looking to do is load all files named init.php in each vc_elements subfolder.

Assuming you mean only immediate sub-directorys of "vc_elements" you can use GlobIterator with an "*" as a subdirectory wildcard:

$myInitFiles = new GlobIterator('/path/to/vc_elements/*/init.php');
foreach ($myInitFiles as $file) {
  require_once( $myInitFiles->key() );
}
unset($myInitFiles);  // release object memory for garbage collection

You can obviously convert this to a more general function if required.

scytale
  • 1,339
  • 1
  • 11
  • 14
0

Not sure what the file structor is for your theme but if you have a folder like inc or int make a file called vc-functions.php in that file do something like this.

add_action( 'vc_before_init', 'vc_before_init_actions' );

function vc_before_init_actions() {
    require_once('vc_elements/text-image/init.php' );
    require_once('vc_elements/text/init.php' );
}

Then in the functions.php

require get_template_directory() . '/inc/vc-functions.php';
Nick Cappello
  • 341
  • 3
  • 12