Your IP : 216.73.216.41


Current Path : /home/purehotels/public_html/components/com_easyfolderlistingpro/helpers/
Upload File :
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));
		}
	}
}