Extending CodeIgniter’s File Helper – Part 1

Although CodeIgniter has been taking a beating, and many developers have moved on to more cutting edge frameworks, I’ve still got projects going in CodeIgniter, so I keep coming up with ways to extend the core, libraries, and helpers.

I want to show you how to extend CodeIgniter’s File Helper to change the way the get_filenames function retrieves files in a directory. With no option to choose whether or not it should recursively retrieve files in sub-directories, the original get_filenames function will go as deep as it can, retrieving files in sub-directories that you may not want.

The Basics of Extending CodeIgniter Helpers

CodeIgniter helpers are simply files that contain regular PHP functions. They are all located in the system directory, inside a directory named “helpers”. You never want to directly edit files located in or within the system directory, so you will create a file named MY_file_helper.php and save it in the helpers sub-directory which resides in your application directory.

When you want to customize one of the file helper’s functions, you will simply create a function in your helper file, naming it the same as the original function’s name. Since we are going to be changing the functionality of the get_filenames function, you should copy and paste the original get_filenames function into your helper file.

The original function is wrapped in an if statement that checks if the function already exists. It doesn’t hurt to leave this if statement wrapping the function you put in your file, but it is not needed, so you can remove it if you like.

/**
 * You can remove this if statement as it is
 * only needed by the original helper because
 * your helper will be loaded first.
 */
if ( ! function_exists('get_filenames'))
{
  // ...
}

A New Parameter

The get_filenames function in our helper will have a new third parameter, and the existing third parameter will become the fourth parameter. This won’t change the way you use the function, since the original third parameter is an internal variable.

function get_filenames( $source_dir, $include_path = FALSE, $include_subdirs = TRUE, $_recursion = FALSE )
{
  // ...
}

By default this parameter is set to TRUE, because we want to maintain backwards compatibility with the original function. Anybody that uses get_filenames will not have to worry about our function breaking their code.

Blocking Recursion

Once the directory has been opened by the function, it loops through the contents and determines if it is dealing with files or a directories. The trick here is that once it determines it is dealing with a directory, we want it to check our new third parameter to see if we are allowing recursion.

// If we want subdirs
if( $include_subdirs === TRUE )
{
  // Notice the new third parameter here also
  get_filenames( $source_dir . $file . DIRECTORY_SEPARATOR, $include_path, TRUE, TRUE );
}

So, after making these modifications, if we want to use get_filenames and don’t want sub-directories to be included, we simply set the third parameter to FALSE.

// Example usage
get_filenames( 'some_directory', FALSE, FALSE );

Here is the complete MY_file_helper.php file:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * Get Filenames
 *
 * Reads the specified directory and builds an array containing the filenames.
 *
 * @access public
 * @param  string  path to source
 * @param  bool  whether to include the path as part of the filename
 * @param  bool  whether to include the files in sub directories
 * @param  bool  internal variable to determine recursion status - do not use in calls
 * @return  array
 */
function get_filenames( $source_dir, $include_path = FALSE, $include_subdirs = TRUE, $_recursion = FALSE )
{
  static $_filedata = array();

  if( $fp = @opendir( $source_dir ) )
  {
    // reset the array and make sure $source_dir has a trailing slash on the initial call
    if( $_recursion === FALSE )
    {
      $_filedata = array();
      $source_dir = rtrim( realpath( $source_dir ), DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR;
    }

    while( FALSE !== ( $file = readdir( $fp ) ) )
    {
      // If a subdir
      if( @is_dir( $source_dir . $file ) && strncmp( $file, '.', 1 ) )
      {
        // If we want subdirs
        if( $include_subdirs === TRUE )
        {
          get_filenames( $source_dir . $file . DIRECTORY_SEPARATOR, $include_path, TRUE, TRUE );
        }
      }

      // else if a normal file
      else if( strncmp( $file, '.', 1 ) !== 0 )
      {
        $_filedata[] = ( $include_path == TRUE ) ? $source_dir . $file : $file;
      }
    }

    return $_filedata;
  }
  else
  {
    return FALSE;
  }
}

// --------------------------------------------------------------------

One thought on “Extending CodeIgniter’s File Helper – Part 1”

Comments are closed.