Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with DPMedia (filesystem plugins) #311

Merged
merged 20 commits into from
Jan 25, 2025
Merged
Changes from 12 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions administrator/com_joomgallery/forms/image.xml
Original file line number Diff line number Diff line change
@@ -24,6 +24,13 @@
<field name="uuid"
type="hidden" />

<field name="filesystem"
type="text"
Elfangor93 marked this conversation as resolved.
Show resolved Hide resolved
readonly="true"
default="local-images"
class="readonly"
label="COM_JOOMGALLERY_CONFIG_FILESYSTEM" />

<field name="hits"
type="text"
readonly="true"
Original file line number Diff line number Diff line change
@@ -787,6 +787,7 @@ COM_JOOMGALLERY_SERVICE_ERROR_CREATE_FILE="File could not be created."
COM_JOOMGALLERY_SERVICE_ERROR_FILESYSTEM_NOT_A_DIRECTORY="Requested path is not a directory."
COM_JOOMGALLERY_SERVICE_ERROR_FILESYSTEM_NOT_FOUND="No filesystem plugin available for the specified adapter (%s)."
COM_JOOMGALLERY_SERVICE_ERROR_FILESYSTEM_ERROR="Filesystem plugin is reporting the following error: %s"
COM_JOOMGALLERY_SERVICE_ERROR_FILESYSTEM_PLUGIN_NOT_ENABLED="It seems that the required filesystem plugin (%s) is not installed or not enabled. Please install and enable the plugin <a href=\"%s\">here</a>."
COM_JOOMGALLERY_SERVICE_MIGRATION_CHECK_TITLE="Check results"
COM_JOOMGALLERY_SERVICE_MIGRATION_GENERAL_PRECHECK_DESC="General checks like log file, site state, ..."
COM_JOOMGALLERY_SERVICE_MIGRATION_SOURCE_PRECHECK_DESC="Check source extension, directories and tables if they are compatible and existent."
1 change: 1 addition & 0 deletions administrator/com_joomgallery/sql/install.mysql.utf8.sql
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ CREATE TABLE IF NOT EXISTS `#__joomgallery` (
`imgmetadata` TEXT NOT NULL,
`published` TINYINT(1) NOT NULL DEFAULT 0,
`filename` VARCHAR(255) NOT NULL,
`filesystem` VARCHAR(100) NOT NULL DEFAULT "local-images",
`hits` INT(11) UNSIGNED NOT NULL DEFAULT 0,
`downloads` INT(11) UNSIGNED NOT NULL DEFAULT 0,
`votes` INT(11) UNSIGNED NOT NULL DEFAULT 0,
1 change: 1 addition & 0 deletions administrator/com_joomgallery/sql/updates/mysql/4.0.0.sql
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ CREATE TABLE IF NOT EXISTS `#__joomgallery` (
`imgmetadata` TEXT NOT NULL,
`published` TINYINT(1) NOT NULL DEFAULT 0,
`filename` VARCHAR(255) NOT NULL,
`filesystem` VARCHAR(100) NOT NULL DEFAULT "local-images",
`hits` INT(11) UNSIGNED NOT NULL DEFAULT 0,
`downloads` INT(11) UNSIGNED NOT NULL DEFAULT 0,
`votes` INT(11) UNSIGNED NOT NULL DEFAULT 0,
51 changes: 51 additions & 0 deletions administrator/com_joomgallery/src/Helper/JoomHelper.php
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
use \Joomla\CMS\Access\Access;
use \Joomla\CMS\Filesystem\Path;
use \Joomla\CMS\Http\HttpFactory;
use \Joomla\CMS\Plugin\PluginHelper;
use \Joomla\CMS\Language\Multilanguage;
use \Joomla\Database\DatabaseInterface;

@@ -1051,6 +1052,56 @@ public static function fetchXML(string $uri): \SimpleXMLElement
return new \SimpleXMLElement($xmlString);
}

/**
* Method to check whether all needed filesystem plugins are available and enabled.
*
* @return bool
*
* @since 4.0.0
*/
public static function checkFilesystems()
Elfangor93 marked this conversation as resolved.
Show resolved Hide resolved
{
// Load all used filesystems from images table
$db = Factory::getContainer()->get(DatabaseInterface::class);

$query = $db->getQuery(true)
->select('DISTINCT ' .$db->quoteName('filesystem'))
->from(_JOOM_TABLE_IMAGES)
->where($db->quoteName('published') . ' = 1');

$db->setQuery($query);
$filesystems = $db->loadColumn();

// Loop through all found filesystems
foreach ($filesystems as $key => $filesystem)
{
// Get corresponding plugin name
$plugin_name = \explode('-', $filesystem, 2)[0];
$plugin_fullname = 'plg_filesystem_'.$plugin_name;

if(!PluginHelper::isEnabled('filesystem', $plugin_name))
{
// Plugin is not installed or not enabled. Show warning message.
$lang = Factory::getLanguage();

if(!$lang->getPaths($plugin_fullname))
{
// Language file is not available
$langFile = JPATH_PLUGINS . '/filesystem/' . $plugin_name;

// Try to load plugin language file
$lang->load($plugin_fullname);
$lang->load($plugin_fullname, $langFile);
}

$plugins_url = Route::_('index.php?option=com_plugins&view=plugins&filter[folder]=filesystem');
$plugin_title = Text::_($plugin_fullname);

self::getComponent()->setWarning(Text::sprintf('COM_JOOMGALLERY_SERVICE_ERROR_FILESYSTEM_PLUGIN_NOT_ENABLED', $plugin_title, $plugins_url));
}
}
}

/**
* Returns a list of all available access action names available
*
2 changes: 1 addition & 1 deletion administrator/com_joomgallery/src/Model/ImageModel.php
Original file line number Diff line number Diff line change
@@ -1080,7 +1080,7 @@ public function recreate(int $pk, $type='original'): bool
}

// Perform the recreation
if(!$this->component->getFileManager()->createImages($source, $table->filename, $table->catid))
if(!$this->component->getFileManager()->createImages($source, $table->filename, $table->catid, true, false, [$type]))
{
$this->setError($table->getError());

Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
\defined('_JEXEC') or die;

use \Joomla\CMS\Language\Text;
use \Joomla\CMS\Filesystem\Path;
use \Joomgallery\Component\Joomgallery\Administrator\Helper\JoomHelper;
use \Joomgallery\Component\Joomgallery\Administrator\Extension\ServiceTrait;
use \Joomgallery\Component\Joomgallery\Administrator\Service\FileManager\FileManagerInterface;
@@ -93,18 +94,19 @@ public function __construct($catid, $selection=False)
/**
* Creation of image types based on source file.
* Source file has to be given with a full system path.
*
*
* @param string $source Source file with which the image types shall be created
* @param string $filename Name for the files to be created
* @param object|int|string $cat Object, ID or alias of the corresponding category (default: 2)
* @param bool $processing True to create imagetypes by processing source (default: True)
* @param bool $processing True to create imagetypes by processing source (defualt: True)
* @param bool $local_source True if the source is a file located in a local folder (default: True)
* @param array $skip List of imagetypes to skip creation (default: [])
*
* @return bool True on success, false otherwise
*
* @since 4.0.0
*/
public function createImages($source, $filename, $cat=2, $processing=True): bool
public function createImages($source, $filename, $cat=2, $processing=True, $local_source=True, $skip=[]): bool
{
if(!$filename)
{
@@ -131,6 +133,13 @@ public function createImages($source, $filename, $cat=2, $processing=True): bool
// Debug info
$this->component->addDebug(Text::sprintf('COM_JOOMGALLERY_SERVICE_PROCESSING_IMAGETYPE', $imagetype->typename), true, true);

if(\in_array($imagetype->typename, $skip) || \in_array($imagetype->type_alias, $skip))
{
$this->component->addDebug(Text::_('COM_JOOMGALLERY_SERVICE_MANIPULATION_NOT_NEEDED'));

continue;
}

// For original images: check if processing is really needed
if( $imagetype->typename == 'original' && $processing &&
$imagetype->params->get('jg_imgtypeanim', 0) == 1 &&
@@ -170,12 +179,41 @@ public function createImages($source, $filename, $cat=2, $processing=True): bool

// Grap resource if needed
$isStream = false;
if(\strpos($this->component->getFilesystem()->getFilesystem(), 'local') === false)
if(\is_resource($source))
{
// We are dealing with an external filesystem
$source = $this->component->getFilesystem()->getResource($source);
$isStream = true;
}
elseif(\is_string($source) && !$local_source && \strpos($this->component->getFilesystem()->getFilesystem(), 'local') === false)
{
// The path is pointing to an external filesystem
list($file_info, $source) = $this->component->getFilesystem()->getResource($source);
$isStream = true;
}
elseif(\is_string($source) && ($local_source || \strpos($this->component->getFilesystem()->getFilesystem(), 'local') !== false))
{
// The path is pointing to the local filesystem
$source = Path::clean($source);

if(!\file_exists($source))
{
// Add root to the path
$source = JPATH_ROOT.\DIRECTORY_SEPARATOR.$source;

$source = Path::clean($source);
}
}
else
{
// Destroy the IMGtools service
$this->component->delIMGtools();

// Debug info
$this->component->addDebug(Text::sprintf('COM_JOOMGALLERY_SERVICE_ERROR_CREATE_IMAGETYPE', $filename, $imagetype->typename));
$this->component->addLog(Text::sprintf('COM_JOOMGALLERY_SERVICE_ERROR_CREATE_IMAGETYPE', $filename, $imagetype->typename), 'error', 'jerror');
$error = true;

continue;
}

// Read source image
if(!$this->component->getIMGtools()->read($source, $isStream))
@@ -266,11 +304,12 @@ public function createImages($source, $filename, $cat=2, $processing=True): bool
$folder = \dirname($file);
try
{
$res = $this->component->getFilesystem()->createFolder(\basename($folder), \dirname($folder));
$res = $this->component->getFilesystem()->createFolder(\basename($folder), \dirname($folder), false);
}
catch(\FileExistsException $e)
catch(FileExistsException $e)
{
// Do nothing
// Folder already exists.
$res = true;
}
catch(\Exception $e)
{
Original file line number Diff line number Diff line change
@@ -29,17 +29,18 @@ interface FileManagerInterface
* Creation of image types based on source file.
* Source file has to be given with a full system path.
*
*
* @param string $source Source file with which the image types shall be created
* @param string $filename Name for the files to be created
* @param object|int|string $cat Object, ID or alias of the corresponding category (default: 2)
* @param bool $processing True to create imagetypes by processing source (default: True)
*
* @param bool $processing True to create imagetypes by processing source (defualt: True)
* @param bool $local_source True if the source is a file located in a local folder (default: True)
* @param array $skip List of imagetypes to skip creation (default: [])
*
* @return bool True on success, false otherwise
*
* @since 4.0.0
*/
public function createImages($source, $filename, $cat=2, $processing=True): bool;
public function createImages($source, $filename, $cat=2, $processing=True, $local_source=True, $skip=[]): bool;

/**
* Deletion of image types
68 changes: 56 additions & 12 deletions administrator/com_joomgallery/src/Service/Filesystem/Filesystem.php
Original file line number Diff line number Diff line change
@@ -98,7 +98,7 @@ public function __construct(string $filesystem = '')
else
{
// Define filesystem adapter based on configuration 'jg_filesystem'
$this->component->getConfig()->get('jg_filesystem','local-images');
$this->filesystem = $this->component->getConfig()->get('jg_filesystem','local-images');
}

// Load language of com_media
@@ -310,11 +310,18 @@ public function getFile(string $path = '/', array $options = []): \stdClass
catch (\Exception $e)
{
$msg = $e->getMessage();
if(\strpos($e->getMessage(), 'account') !== false || \strpos($e->getMessage(), 'Account') !== false)
if(\strpos(\strtolower($e->getMessage()), 'account'))
{
$this->component->addLog(Text::_('COM_JOOMGALLERY_SERVICE_ERROR_FILESYSTEM_NOT_FOUND'), 'error', 'jerror');
throw new \Exception(Text::sprintf('COM_JOOMGALLERY_SERVICE_ERROR_FILESYSTEM_NOT_FOUND', $adapter));
}
elseif(\strpos(\strtolower($e->getMessage()), 'no such file') !== false)
{
$this->component->addLog('FileNotFoundException in function getFile in Filesystem.php: ' . Text::_('COM_JOOMGALLERY_SERVICE_ERROR_FILENOTFOUND'), 'warning', 'jerror');
$this->component->addLog('$adapter: ' . $adapter, 'warning', 'jerror');
$this->component->addLog('$path: ' . $path, 'warning', 'jerror');
throw new FileNotFoundException(Text::_('COM_JOOMGALLERY_SERVICE_ERROR_FILENOTFOUND'));
}
else
{
$this->component->addLog($e->getMessage(), 'error', 'jerror');
@@ -336,7 +343,7 @@ public function getFile(string $path = '/', array $options = []): \stdClass

if(isset($options['content']) && $options['content'] && $file->type == 'file')
{
$resource = $this->getAdapter($adapter)->getResource($file->path);
list($file_info, $resource) = $this->getAdapter($adapter)->getResource($file->path);

if($resource)
{
@@ -403,7 +410,7 @@ public function getFiles(string $path = '/', array $options = []): array

if(isset($options['content']) && $options['content'] && $file->type == 'file')
{
$resource = $this->getAdapter($adapter)->getResource($file->path);
list($file_info, $resource) = $this->getAdapter($adapter)->getResource($file->path);

if($resource)
{
@@ -431,14 +438,15 @@ public function getFiles(string $path = '/', array $options = []): array
* @param string $name The name
* @param string $path The folder
* @param boolean $override Should the folder being overridden when it exists (default: true)
* @param boolean $loop True, if we are in a recursive loop (default: false)
*
* @return string The folder name
*
* @since 4.0.0
* @throws \Exception
* @see AdapterInterface::createFolder()
*/
public function createFolder(string $name, string $path, bool $override = true): string
public function createFolder(string $name, string $path, bool $override = true, bool $loop = false): string
{
$adapter = $this->getFilesystem();
$path = $this->cleanPath($this->adjustPath($path), '/');
@@ -449,14 +457,13 @@ public function createFolder(string $name, string $path, bool $override = true):
}
catch (FileNotFoundException $e)
{
// Do nothing
// Folder not found; proceed to create it
}

// Check if the file exists
if
(isset($file) && !$override)
if (isset($file) && !$override)
{
throw new FileExistsException();
// No need to create folders
throw new FileExistsException('Folder already exists: ' . $path . '/' . $name);
}

$object = new CMSObject();
@@ -468,12 +475,49 @@ public function createFolder(string $name, string $path, bool $override = true):

$result = $this->app->triggerEvent('onContentBeforeSave', ['com_media.folder', $object, true, $object]);

if(in_array(false, $result, true))
if(\in_array(false, $result, true))
{
throw new \Exception($object->getError());
}

$object->name = $this->getAdapter($object->adapter)->createFolder($object->name, $object->path);
try
{
// Try to create folders recursively
$object->name = $this->getAdapter($object->adapter)->createFolder($object->name, $object->path);
}
catch (\Exception $e)
{
if(!$loop)
{
// If it doesnt work like that, try again by creating them one by one
$folders = \explode('/', trim($object->path, '/'));
$leading_slash = \strpos($object->path, '/') === 0;
$currentPath = $leading_slash ? '/' : '';

// Append the current folder to the folders array
$folders[] = $object->name;

foreach($folders as $folder)
{
try
{
// Create each folder one by one
$object->name = $this->createFolder($folder, $currentPath, $override, true);
}
catch (FileExistsException $fee)
{
// Folder already exists; no action needed
}

// Adjust the currently existing path
$currentPath .= ($currentPath === '/' ? '' : '/') . $folder;
}
}
else
{
throw new \Exception($e->getMessage());
}
}

$this->app->triggerEvent('onContentAfterSave', ['com_media.folder', $object, true, $object]);

Original file line number Diff line number Diff line change
@@ -207,6 +207,9 @@ public function retrieveImage(&$data, $filename=True): bool
}
}

// Set filesystem
$data['filesystem'] = $this->component->getFilesystem()->get('filesystem');

// Trigger onJoomBeforeUpload
$plugins = $this->app->triggerEvent('onJoomBeforeUpload', array($data['filename']));
if(in_array(false, $plugins, true))
Loading