Server : LiteSpeed System : Linux server 3.10.0-1160.90.1.el7.x86_64 #1 SMP Thu May 4 15:21:22 UTC 2023 x86_64 User : alsaif ( 1057) PHP Version : 7.4.33 Disable Function : show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/alsaif/public_html/plugins/system/nrframework/NRFramework/Helpers/Widgets/ |
<?php
/**
* @author Tassos Marinos <info@tassos.gr>
* @link https://www.tassos.gr
* @copyright Copyright © 2024 Tassos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
namespace NRFramework\Helpers\Widgets;
defined('_JEXEC') or die;
use NRFramework\Mimes;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;
class Gallery
{
/**
* Stores all gallery parsed directories info txt file `*.gallery_info.txt` data in format:
* GALLERY DIRECTORY => ARRAY OF `*.gallery_info.txt` file data
*
* @var array
*/
static $gallery_directories_info_file = [];
/**
* Stores all galleries info file names in format:
*
* GALLERY DIRECTORY => INFO FILE NAME
*
* @var array
*/
static $gallery_directories_info_file_names = [];
/**
* The directory information file holding all gallery item details.
*
* @var string
*/
const directory_gallery_info_file = 'gallery_info.txt';
/**
* Parses the given gallery items.
*
* @param mixed $input A string to a directory/path/URL or an array of a URL item containing its information.
* @param array $allowed_file_types The allowed file types.
*
* @return mixed
*/
public static function parseGalleryItems($input, $allowed_file_types = [])
{
if (is_string($input))
{
$fullpath_input = JPATH_ROOT . DIRECTORY_SEPARATOR . ltrim($input, DIRECTORY_SEPARATOR);
// Parse Directory
if (is_dir($fullpath_input))
{
return self::parseDirectory($fullpath_input, $allowed_file_types);
}
// Skip invalid URLs
if ($url = self::parseURL($input))
{
return [$url];
}
// Parse Image
if ($image_data = self::parseImage($fullpath_input, $allowed_file_types))
{
return [$image_data];
}
}
return [self::parseURL($input)];
}
/**
* Parse the directory by finding all of its images and their information.
*
* @param string $dir
* @param array $allowed_file_types
*
* @return mixed
*/
public static function parseDirectory($dir, $allowed_file_types = [])
{
if (!is_string($dir) || !is_dir($dir) || empty($allowed_file_types))
{
return;
}
$items = [];
// Get images
$files = array_diff(scandir($dir), ['.', '..', '.DS_Store']);
foreach ($files as $key => $filename)
{
// Skip directories
if (is_dir($dir . DIRECTORY_SEPARATOR . $filename))
{
continue;
}
$image_path = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $filename;
if (!$image_data = self::parseImage($image_path, $allowed_file_types))
{
continue;
}
$items[] = $image_data;
}
return $items;
}
/**
* Parse the directory image and return its information.
*
* @param string $image_path
* @param string $allowed_file_types
*
* @return mixed
*/
public static function parseImage($image_path, $allowed_file_types = null)
{
if (!is_string($image_path))
{
return;
}
$data = [
'path' => $image_path,
'url' => self::directoryImageToURL($image_path)
];
if (!is_file($image_path))
{
return array_merge($data, [
'invalid' => true
]);
}
// Skip not allowed file types
if (!is_null($allowed_file_types) && !Mimes::check($allowed_file_types, Mimes::detectFileType($image_path)))
{
return;
}
// Check if there is a `*.gallery_info.txt` helper file and get any information about the image
$gallery_info_file_data = self::getGalleryInfoFileData(dirname($image_path));
if (!$gallery_info_file_data)
{
return $data;
}
$image_filename = pathinfo($image_path, PATHINFO_BASENAME);
// If no information from the text field about this image was found, stop
if (!isset($gallery_info_file_data[$image_filename]))
{
return $data;
}
$image_data = $gallery_info_file_data[$image_filename];
return array_merge($data, [
'caption' => isset($image_data['caption']) ? $image_data['caption'] : ''
]);
}
/**
* Parses a single URL either as a String or as an Array.
*
* @param mixed $item
*
* @return mixed
*/
public static function parseURL($item)
{
// URL is a string
if (is_string($item))
{
if (!filter_var($item, FILTER_VALIDATE_URL))
{
return;
}
return [
'url' => $item
];
}
// URL is an array
if (!is_array($item) || !count($item))
{
return;
}
// If a thumbnail URL is given but no URL, use it as the full image URL
if (isset($item['thumbnail_url']) && !isset($item['url']))
{
$item['url'] = $item['thumbnail_url'];
}
if (!isset($item['url']))
{
return;
}
if (!filter_var($item['url'], FILTER_VALIDATE_URL))
{
return;
}
return $item;
}
/**
* Loads a module by its ID.
*
* @param string $id
*
* @return string
*/
public static function loadModule($id)
{
$module = ModuleHelper::getModuleById($id);
$params = ['style' => 'none'];
return $module->id > 0 ? Factory::getDocument()->loadRenderer('module')->render($module, $params) : '';
}
/**
* Read the `*.gallery_info.txt` file for the given directory.
*
* @param string $dir
*
* @return mixed
*/
public static function getGalleryInfoFileData($dir)
{
if (isset(self::$gallery_directories_info_file[$dir]) && !empty(self::$gallery_directories_info_file[$dir]))
{
return self::$gallery_directories_info_file[$dir];
}
if (!$file = self::findGalleryInfoFile($dir))
{
return [];
}
// Read file
if (!$handle = fopen($file, 'r'))
{
return [];
}
$data = [];
$line_defaults = ['', '', ''];
// Loop each line
while (($line = fgets($handle)) !== false)
{
list($filename, $caption, $hash) = explode('|', $line) + $line_defaults;
// If no filename is given, continue
if (!$filename)
{
continue;
}
$data[$filename] = [
'filename' => $filename,
'caption' => trim($caption),
'hash' => trim($hash)
];
}
// Close file
fclose($handle);
self::$gallery_directories_info_file[$dir] = $data;
return $data;
}
/**
* Finds the source image and whether it has been edited.
*
* @param string $source
* @param string $destination_folder
*
* @return mixed
*/
public static function findSourceImageDetails($source, $destination_folder)
{
$source_filename = pathinfo($source, PATHINFO_BASENAME);
$data = self::getGalleryInfoFileData(dirname($source));
$image_data = isset($data[$source_filename]) ? $data[$source_filename] : false;
if (!$image_data)
{
return false;
}
if (empty($image_data['hash']))
{
return false;
}
$sourceHash = self::calculateFileHash($source);
return [
'path' => $destination_folder . $image_data['filename'],
'edited' => $image_data['hash'] !== $sourceHash
];
}
/**
* Updates or Inserts the given image information from the gallery info file.
*
* @param string $source
* @param array $image_data
*
* @return mixed
*/
public static function updateImageDataInGalleryInfoFile($source, $image_data)
{
// Source directory
$source_directory = dirname($source);
// Check whether the gallery info file exists, if not, create it
if (!$file = self::findGalleryInfoFile($source_directory))
{
$file = self::createGalleryInfoFile($source_directory);
}
// Open files
$reading = fopen($file, 'r');
$writing = fopen($file . '.tmp', 'w');
$replaced = false;
while (!feof($reading))
{
// Get each file line
$line = fgets($reading);
// Remove new line at the end
$line = trim(preg_replace('/\s\s+/', ' ', $line));
// Skip empty lines
if (empty($line))
{
continue;
}
list($filename, $caption, $hash) = explode('|', $line) + ['', '', ''];
// We need to manipulate current file
if (strtolower($filename) !== strtolower(basename($image_data['path'])))
{
fputs($writing, $line . "\n");
continue;
}
$replaced = true;
$line = $filename . '|' . $caption . '|' . self::calculateFileHash($source) . "\n";;
// Write changed line
fputs($writing, $line);
}
// Close files
fclose($reading);
fclose($writing);
// If we replaced a line, update the text file
if ($replaced)
{
rename($file . '.tmp', $file);
}
// No line was replaced, append image details
else
{
unlink($file . '.tmp');
self::appendImageDataToGalleryInfoFile($file, $source, $image_data);
}
}
/**
* Removes the image from the gallery info file.
*
* @param string $source
*
* @return boolean
*/
public static function removeImageFromGalleryInfoFile($source)
{
// Get the gallery info file from destination folder
if (!$file = self::findGalleryInfoFile(dirname($source)))
{
return false;
}
// Open files
$reading = fopen($file, 'r');
$writing = fopen($file . '.tmp', 'w');
$found = false;
while (!feof($reading))
{
// Get each file line
$line = fgets($reading);
// Remove new line at the end
$line = trim(preg_replace('/\s\s+/', ' ', $line));
// Skip empty lines
if (empty($line))
{
continue;
}
list($filename, $caption, $hash) = explode('|', $line) + ['', '', ''];
// We need to manipulate current file
if ($filename !== pathinfo($source, PATHINFO_BASENAME))
{
$found = true;
fputs($writing, $line . "\n");
continue;
}
}
// Close files
fclose($reading);
fclose($writing);
if (!$found)
{
return false;
}
// Save the changes
rename($file . '.tmp', $file);
return true;
}
/**
* Appends the image data into the info file.
*
* @param string $dir
*
* @return void
*/
public static function createGalleryInfoFile($dir)
{
$file = self::getLanguageInfoFileName($dir);
file_put_contents($file, '');
return $file;
}
/**
* Appends the image data into the info file.
*
* @param string $file
* @param string $source
* @param object $image_data
*
* @return void
*/
public static function appendImageDataToGalleryInfoFile($file, $source, $image_data)
{
$caption = isset($image_data['caption']) ? $image_data['caption'] : '';
$hash = self::calculateFileHash($source);
$line = pathinfo($source, PATHINFO_BASENAME) . '|' . $caption . '|' . $hash . "\n";
file_put_contents($file, $line, FILE_APPEND);
}
/**
* Finds the `*.gallery_info.txt` file if it exists in the given directory.
*
* @param string $dir
*
* @return mixed
*/
public static function findGalleryInfoFile($dir)
{
if (isset(self::$gallery_directories_info_file_names[$dir]))
{
return self::$gallery_directories_info_file_names[$dir];
}
// Method 1: With language prefix
$file = self::getLanguageInfoFileName($dir);
// Check if the file exists
if (file_exists($file))
{
self::$gallery_directories_info_file_names[$dir] = $file;
return $file;
}
// Method 2: Without the language prefix
$file = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . self::directory_gallery_info_file;
// Check if the file exists
if (file_exists($file))
{
self::$gallery_directories_info_file_names[$dir] = $file;
return $file;
}
return false;
}
/**
* Returns the info file with the language prefix.
*
* @param string $dir
*
* @return string
*/
public static function getLanguageInfoFileName($dir)
{
return rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . Factory::getLanguage()->getTag() . '.' . self::directory_gallery_info_file;
}
/**
* Calculates the file hash of a file.
*
* Hash = md5(file path + last modified date of file)
*
* @param string $file_path
*
* @return string
*/
public static function calculateFileHash($file_path)
{
return md5($file_path . filemtime($file_path));
}
/**
* Transforms an image path to a URL.
*
* @param string $image_path
*
* @return string
*/
public static function directoryImageToURL($image_path)
{
return rtrim(Uri::root(), DIRECTORY_SEPARATOR) . mb_substr($image_path, strlen(JPATH_BASE), null);;
}
}