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?
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.
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.
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;
}
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';
Related
I have a top folder named home and nested folders and files inside
I need to insert some data from files and folders into a table
The following (simplified) code works fine if I manually declare parent folder for each level separatelly, i.e. - home/lorem/, home/impsum/, home/ipsum/dolor/ etc
Is there a way to do this automatically for all nested files and folders ?
Actually, I need the path for each of them on each level
$folders = glob("home/*", GLOB_ONLYDIR);
foreach($folders as $el){
//$path = ??;
//do_something_with folder;
}
$files = glob("home/*.txt");
foreach($files as $el){
//$path = ??;
//do_something_with file;
}
PHP has the recursiveIterator suite of classes - of which the recursiveDirectoryIterator is the correct tool for the task at hand.
# Where to start the recursive scan
$dir=__DIR__;
# utility
function isDot( $dir ){
return basename( $dir )=='.' or basename( $dir )=='..';
}
# create new instances of both recursive Iterators
$dirItr=new RecursiveDirectoryIterator( $dir, RecursiveDirectoryIterator::KEY_AS_PATHNAME );
$recItr=new RecursiveIteratorIterator( $dirItr, RecursiveIteratorIterator::CHILD_FIRST );
foreach( $recItr as $obj => $info ) {
# directories
if( $info->isDir() && !isDot( $info->getPathname() ) ){
printf('> Folder=%s<br />',realpath( $info->getPathname() ) );
}
# files
if( $info->isFile() ){
printf('File=%s<br />',$info->getFileName() );
}
}
I would suggest you to use The Finder Component
use Symfony\Component\Finder\Finder;
$finder = new Finder();
// find all files in the home directory
$finder->files()->in('home/*');
// To output their path
foreach ($finder as $file) {
$path = $file->getRelativePathname();
}
I need to delete files that start with a prefix in a certain folder in my Symfony project. I have used the following code to delete for example the files start with p_ (p_example.jpeg), but do not delete them:
Php:
public function exampleAction(){
$Dir = $this->container->getParameter('kernel.root_dir').'/../web/uploads/news/';
$files=glob("'".$Dir."p_*.*'",GLOB_MARK);
foreach($files as $file){
if(is_file($file)){
unlink($file);
}
}
}
I appreciate your help.
Finally, I have resolved it with the following code:
Php:
public function exampleAction(){
$Dir = $this->container->getParameter('kernel.root_dir').'/../web/uploads/news/';
$mask = $Dir."p_*.*";
array_map( "unlink", glob( $mask ) );
}
I wan't to write a function which auto autoloads :) models based on files in folder model. So the application has to scan folder for files, grep all .php files, remove . and .. "folders" and place them in autoload['model'] = array
This is my current code in autoload.php file
$dir = './application/models';
$files = scandir($dir);
unset($files[0]);
unset($files[1]);
$mods = '';
foreach ($files as $f){
if(glob('*.php') ){
$mods .= str_replace('.php','',"'".$f."',");
}
}
$autoload['model'] = $mods;
And i'm keep getting errors like
An uncaught Exception was encountered
Type: RuntimeException
Message: Unable to locate the model you have specified: 'admins','categories','companies','countries'
Filename: D:\wamp64\www\myapp\public_html\rest\system\core\Loader.php
Line Number: 344
It looks like the problem is that when i pass array to $autoload variable it threats whole array as one model. Can you guys help me fix my problem.
I would go for something like:
/application/config/autoload.php
autoload['model'] = array('autoload_models');
/application/models/Autoload_models_model.php
class Autoload_models_model extends CI_Model {
public function __construct(){
parent::__construct();
// Scan directory where this (Autoload_models_model.php) file is located
$model_files = scandir(__DIR__);
foreach($model_files as $file){
// Make sure we are not reloading autoload_models_model
// Make sure we have a PHP file
if(
strtolower(explode('.', $file)[0]) !== strtolower(__CLASS__) &&
strtolower(explode('.', $file)[1]) === 'php')
{
$this->load->model(strtolower($file));
}
}
}
}
This is the solution that worked for me. If you find any shorter or nicer code please let me know
$dir = './application/models';
$files = scandir($dir);
$models = array();
foreach ($files as $f){
$file_parts = pathinfo($f);
$file_parts['extension'];
$correct_extension = Array('php');
if(in_array($file_parts['extension'], $correct_extension)){
array_push($models, str_replace('.php','',$f));
}
}
$autoload['model'] = $models;
/* autoload model */
function iteratorFileRegex( $dir, $regex )
{
$files = new FilesystemIterator( $dir );
$files = new RegexIterator( $files, $regex );
$models = array();
foreach ( $files as $file )
{
$models[] = pathinfo( $file, PATHINFO_FILENAME ); // Post_Model
}
return $models;
}
$autoload['model'] = iteratorFileRegex( APPPATH . "models", "/^.*\.(php)$/" );
I need to load index.php file from each of the plugins' folders. There is the main folder "plugins" and inside there are, sub folders (plugins) e.g blog, members etc. Inside each plugin folder there is an index.php file which i need to load. How can i load the directory and search for these files. The plugin folders are not static and might change.
What i have tried
$dir_iterator = new RecursiveDirectoryIterator($this->plugin_dir);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
// could use CHILD_FIRST if you so wish
foreach ($iterator as $file) {
echo $file, "\n";
}
and..the glob function (which didn't help much
$list = glob('index.php', GLOB_BRACE);
foreach($list as $files){
echo $files;
}
print_r($list);
I used a double listing way..
private function loadPlugins(){
$dir = array_diff(scandir($this->plugin_dir), array('..', '.'));
foreach($dir as $ds){
$list = glob($this->plugin_dir.'/'.$ds.'/index.php', GLOB_BRACE);
foreach($list as $files){
require $files;
}
}
}
I'm trying to list all PHP files in a specified directory and for it to recursively check all sub-directories until it finds no more, there could be numerous levels.
The function I have below works fine with the exception that it only recurses down one level.
I've spent hours trying to see where I'm going wrong, I'm calling the scanFiles() when it finds a new directory but this only seems to work one level down and stop, any help greatly appreciated.
Updated:
function scanFiles($pParentDirectory)
{
$vFileArray = scandir($pParentDirectory);
$vDirectories = array();
foreach ($vFileArray as $vKey => $vValue)
{
if (!in_array($vValue, array('.', '..')) && (strpos($vValue, '.php') || is_dir($vValue)))
{
if (!is_dir($vValue))
$vDirectories[] = $vValue;
else
{
$vDirectory = $vValue;
$vSubFiles = scanFiles($vDirectory);
foreach ($vSubFiles as $vKey => $vValue)
$vDirectories[] = $vDirectory.DIRECTORY_SEPARATOR.$vValue;
}
}
}
return $vDirectories;
}
You can do this easily like this:
// helper function
function getFiles(&$files, $dir) {
$items = glob($dir . "/*");
foreach ($items as $item) {
if (is_dir($item)) {
getFiles($files, $item);
} else {
if (end(explode('.', $item)) == 'php') {
$files[] = basename($item);
}
}
}
}
// usage
$files = array();
getFiles($files, "myDir");
// debug
var_dump($files);
myDir looks like this: has php files in all dirs
Output:
P.S. if you want the function to return the full path to the found .php files, remove the basename() from this line:
$files[] = basename($item);
This will then produce result like this:
hope this helps.
This is because $vDirectory is just a folder name, so scanDir looks in the current folder for it, not the sub folder.
What you want to do is to pass in the path to the folder, not just the name. This should be as simple as changing your recursive call to scanFiles($pParentDirectory . DIRECTORY_SEPARATOR . $vDirectory)
Your main problem is functions like scanDir or isDir need the full file path to work.
If you pass the full file path to them, it should work correctly.