| Current Path : /home/purehotels/public_html/components/com_easyfolderlistingpro/helpers/ |
| Current File : /home/purehotels/public_html/components/com_easyfolderlistingpro/helpers/ListingData.Class.php |
<?php
/**
* @name ListingData
* @description
* @author Michael Gilkes (Valor Apps)
* @created Thursday, April 03, 2014
* @modified
* @version 1.0
* @copyright Copyright (C) 2012-2016 Michael Albert Gilkes. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
defined('JPATH_PLATFORM') or die;
//load the JFolder library
jimport('joomla.filesystem.folder');
require_once("ValorUtilities.Class.php");
class ListingData extends JObject
{
const IMAGES_EXTS = 'gif,png,jpeg,jpg,bmp';
protected static $sort_algorithm = 'natural';
protected static $sort_column = 'name';
protected static $sort_direction = 'asc';
protected static $folder_sort_dir = 'asc';
protected static $date_type = 'mtime';
protected static $preserve_folders = true;
protected $files;
protected $folders;
public function __construct($properties = null)
{
//initialize the files array
$this->files = array();
//initialize the folders array
$this->folders = array();
parent::__construct($properties);
}
/**
* This gets list of all the files in the designated folder, gets their metadata, and then sort
* the files.
*/
public function getFilesData($ignore_subfolders = false, $preserve_folders = true)
{
//compile the absolute path. All slashes are OS-dependent.
$absolutePath = $this->compilePath();
if (!is_dir($absolutePath))
{
$this->setError(JText::sprintf('PLG_CONTENT_EFLP_LISTING_PATH_NOT_EXIST_ERROR', $absolutePath));
return false;
}
//determine the folder level
$recurse = false;
if (!$ignore_subfolders && $this->get('subfolders'))
{
//must force a cast from string to integer, else maxlevel won't be registered
$recurse = intval($this->get('maxlevel'));
$recurse = (($recurse <= 0)? 0 : $recurse);
}
//get all the files
$temp = JFolder::files($absolutePath, '.', $recurse, true, $this->get('exfiles'));
//get the total number of files
$total = count($temp);
//change all the slashes in absolute path to forward slashes.
$folder = ValorUtilities::changeSlashes($absolutePath, '/');
//process the all data relating to the file
for ($i = 0; $i < $total; $i++)
{
//get info on the file
$parts = ValorUtilities::fixed_pathinfo($temp[$i]);
//force the directory path to only have forward slashes
$parts['dirname'] = str_replace('\\', '/', $parts['dirname']);
//check to see if any folders in the directory path are not listed in the excluded folders
$subfolders = array_filter(explode('/', $parts['dirname']), 'strlen');
$skip = false;
foreach ($subfolders as $sub)
{
$skip = in_array($sub, $this->get('exfolders'));
if ($skip) { break; }
}
//Note: Skip files with no extension. Those are typically system files.
if (!array_key_exists('extension', $parts))
{
$skip = true;
}
//check to see if the file is permitted/forbidden
if ($skip == false && stripos($this->get('forbidden'), $parts['extension']) === false)
{
if ($this->get('whitelist') != '*' && stripos($this->get('whitelist'), $parts['extension']) === false)
{
$skip = true;
}
}
else
{
$skip = true;
}
//skip file if it's folder is in the excluded list
if (!$skip)
{
//set up data array
$filedata = array();
//1. file's filename (without extension)
$filedata['filename'] = $parts['filename'];
//2. file's extension
$filedata['ext'] = $parts['extension'];
//3. file's path relative to listing folder absolute location. (relpath should start with slash)
$filedata['relpath'] = str_replace($folder, '', $parts['dirname']);
//4. add the file's level
$pieces = explode('/', $filedata['relpath']);
$level = (count($pieces) - 1);
$filedata['level'] = $level;
//5. add the subfolder, and 6. the parent
if ($level == 0)
{
$filedata['subfolder'] = '';
$filedata['parent'] = '.';
}
elseif ($level == 1)
{
$filedata['subfolder'] = $pieces[$level];
$filedata['parent'] = '/';
}
else
{
$filedata['subfolder'] = $pieces[$level];
$filedata['parent'] = $pieces[$level-1];
}
//get all the unix stats for the file
$filestats = stat($temp[$i]);
//if "stat()" produces an error, it returns FALSE
//so, checking for 'bytes' or 'mtime' shows that the file exists regardless of error in its statistics
if ($filestats)
{
//7. add the size as bytes
$filedata['bytes'] = $filestats['size'];
//8. add the accessed date/datetime
$filedata['atime'] = $filestats['atime'];
//9. add the created date/datetime
$filedata['ctime'] = $filestats['ctime'];
//10. add the modified date/datetime
$filedata['mtime'] = $filestats['mtime'];
}
else //set both to zero if stat didn't work.
{
//7. add the size as bytes
$filedata['bytes'] = 0;
//8. add the accessed date/datetime
$filedata['atime'] = 0;
//9. add the created date/datetime
$filedata['ctime'] = 0;
//10. add the modified date/datetime
$filedata['mtime'] = 0;
}
//11. image info
$filedata['image'] = $this->imageInfo($temp[$i], $parts['extension']);
//add the file data array
$this->files[] = $filedata;
}
}
//sort the files
$success = $this->sortFiles($preserve_folders);
if (!$success)
{
$this->setError(JText::_('PLG_CONTENT_EFLP_LISTING_SORTING_FILES_ERROR'));
return false;
}
return $this->files;
}
/**
* Checks to see if the path given is an absolute path or relative path. If it is a
* relative path it changes the relative path to an absolute path and cleans it.
* Note that is cleans with DIRECTORY_SEPARATOR.
*
* Also, the folder was already semi-cleaned. Whitespace was removed
* from start and end. Forward slashes and backslahes were removed from
* end. The beginning *could* have a forward slash or a double backslash if UNC.
*/
protected function compilePath()
{
//get the listing path
$path = $this->get('folder');
return ValorUtilities::compilePath($path, $this->get('userfolders'), $this->get('guestfolder'));
}
/**
* Gets the image info if the file is an image. Sets to false if not.
*/
protected function imageInfo($filepath, $ext)
{
$info = false;
if (stripos(self::IMAGES_EXTS, $ext) !== false)
{
$temp = getimagesize($filepath);
$info = array('width' => $temp[0], 'height' => $temp[1]);
}
return $info;
}
protected function sortFiles($preserve_folders = true)
{
//only try to sort a non-empty array of files
if (!empty($this->files))
{
//
self::$sort_algorithm = $this->get('sortalgorithm', 'natural');
self::$sort_column = $this->get('sortcolumn', 'name');
self::$sort_direction = $this->get('sortdirection', 'asc');
self::$folder_sort_dir = $this->get('foldersortdir', 'asc');
self::$date_type = $this->get('datetype', 'mtime');
self::$preserve_folders = $preserve_folders;
return usort($this->files, 'ListingData::cmp');
}
//it is not really an error that there are no files to sort. ;)
return true;
}
protected static function cmp($x, $y)
{
//initialize result variables to zero
$path_result = 0;
$compare_result = 0;
//if we are preserving the folder structure, sort by relative path first
if (self::$preserve_folders)
{
if (self::$folder_sort_dir == 'desc')
{
$path_result = call_user_func('ListingData::cmp_text_'.self::$sort_algorithm, $y['relpath'], $x['relpath']);
}
else //self::$folder_sort_dir == 'asc'
{
$path_result = call_user_func('ListingData::cmp_text_'.self::$sort_algorithm, $x['relpath'], $y['relpath']);
}
}
//determine what key we are sorting
if (self::$sort_column == 'size')
{
if (self::$sort_direction == 'desc')
{
$compare_result = call_user_func('ListingData::cmp_int', $y['bytes'], $x['bytes']);
}
else
{
$compare_result = call_user_func('ListingData::cmp_int', $x['bytes'], $y['bytes']);
}
}
elseif (self::$sort_column == 'date')
{
if (self::$sort_direction == 'desc')
{
$compare_result = call_user_func('ListingData::cmp_int', $y[self::$date_type], $x[self::$date_type]);
}
else
{
$compare_result = call_user_func('ListingData::cmp_int', $x[self::$date_type], $y[self::$date_type]);
}
}
else // (self::$sort_column == 'name')
{
if (self::$sort_direction == 'desc')
{
$compare_result = call_user_func('ListingData::cmp_text_'.self::$sort_algorithm, $y['filename'].'.'.$y['ext'], $x['filename'].'.'.$x['ext']);
}
else
{
$compare_result = call_user_func('ListingData::cmp_text_'.self::$sort_algorithm, $x['filename'].'.'.$x['ext'], $y['filename'].'.'.$y['ext']);
}
}
//if we are not preserving the folder structure, sort by relative path last
if (!self::$preserve_folders)
{
if ($compare_result == 0)
{
if (self::$folder_sort_dir == 'desc')
{
$path_result = call_user_func('ListingData::cmp_text_'.self::$sort_algorithm, $y['relpath'], $x['relpath']);
}
else //$foldersortdir == 'asc'
{
$path_result = call_user_func('ListingData::cmp_text_'.self::$sort_algorithm, $x['relpath'], $y['relpath']);
}
}
else
{
return $compare_result;
}
}
else
{
//determine the sort order direction
if ($path_result == 0)
{
return $compare_result;
}
else //the subfolder relative path is different
{
return $path_result;
}
}
}
protected static function cmp_text_normal($x, $y)
{
return strcmp($x, $y);
}
protected static function cmp_text_inormal($x, $y)
{
return strcasecmp($x, $y);
}
protected static function cmp_text_natural($x, $y)
{
return strnatcmp($x, $y);
}
protected static function cmp_text_inatural($x, $y)
{
return strnatcasecmp($x, $y);
}
protected static function cmp_int($x, $y)
{
//make sure the parameters are integers
if (!is_int($x)) { $x = intval($x); }
if (!is_int($y)) { $y = intval($y); }
return $x - $y;
}
public function getFoldersData($ignore_subfolders = false)
{
$absolutePath = $this->compilePath();
if (!is_dir($absolutePath))
{
$this->setError(JText::sprintf('PLG_CONTENT_EFLP_LISTING_PATH_NOT_EXIST_ERROR', $absolutePath));
return false;
}
//determine the folder level
$recurse = false;
if (!$ignore_subfolders && $this->get('subfolders'))
{
//must force a cast from string to integer, else maxlevel won't be registered
$recurse = intval($this->get('maxlevel'));
//folders level are 1 less than files
$recurse = (($recurse <= 0)? 0 : $recurse - 1);
}
//get all the files
$temp = JFolder::folders($absolutePath, '.', $recurse, true, $this->get('exfolders'));
//presort the folders
$algorithm = $this->get('sortalgorithm', 'natural');
$foldersortdir = $this->get('foldersortdir', 'asc');
$sort_success = false;
$sort_success = usort($temp, 'ListingData::cmp_text_'.$algorithm);
if (!$sort_success)
{
$this->setError(JText::_('PLG_CONTENT_EFLP_LISTING_SORTING_FOLDERS_ERROR'));
return false;
}
//reverse order or array to be descending order
if ($foldersortdir == 'desc')
{
$temp = array_reverse($temp);
}
//get the total number of files
$total = count($temp);
//change all the slashes in absolute path to forward slashes.
$folder = ValorUtilities::changeSlashes($absolutePath, '/');
for ($i = 0; $i < $total; $i++)
{
//set up data array
$folderdata = array();
//custom clean path. only want forward slashes.
$path = str_replace('\\', '/', $temp[$i]);
//1. folders relative path
$folderdata['relpath'] = str_replace($folder, '', $path);
//2. add the folder's level
$pieces = explode('/', $folderdata['relpath']);
$level = (count($pieces) - 1);
$folderdata['level'] = $level;
//3.
$folderdata['name'] = $pieces[$level];
//4. add the parent
if ($level <= 1)
{
$folderdata['parent'] = '/';
}
else
{
$folderdata['parent'] = $pieces[$level-1];
}
//add to folder array
$this->folders[] = $folderdata;
}
return $this->folders;
}
public function __printFiles($raw = true)
{
if ($raw)
{
$f = array();
for ($i = 0; $i < count($this->files); $i++)
{
$f[] = $this->get('folder').$this->files[$i]['relpath'].'/'.$this->files[$i]['filename'].'.'.$this->files[$i]['ext'];
}
error_log(print_r($f, true));
}
else
{
error_log(print_r($this->files, true));
}
}
public function __printFolders($raw = true)
{
if ($raw)
{
$f = array();
for ($i = 0; $i < count($this->folders); $i++)
{
$f[] = $this->get('folder').$this->folders[$i]['relpath'];
}
error_log(print_r($f, true));
}
else
{
error_log(print_r($this->folders, true));
}
}
}