Release of v5.0.3-alpha4
Fix database default fields to allow NULL. #1169. Fix the power list field to allow search. #1167. Expanded the Demo component in JCB v4 to include more advance features.
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 3rd September, 2020
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Componentbuilder\File;
|
||||
|
||||
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use VDM\Joomla\Interfaces\Data\ItemInterface as Item;
|
||||
use VDM\Joomla\Interfaces\Data\ItemsInterface as Items;
|
||||
|
||||
|
||||
/**
|
||||
* File Display Class
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
final class Display
|
||||
{
|
||||
/**
|
||||
* The Item Class.
|
||||
*
|
||||
* @var Item
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected Item $item;
|
||||
|
||||
/**
|
||||
* The Items Class.
|
||||
*
|
||||
* @var Items
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected Items $items;
|
||||
|
||||
/**
|
||||
* The file site url
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected string $url;
|
||||
|
||||
/**
|
||||
* The file types
|
||||
*
|
||||
* @var array
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected array $fileTypes;
|
||||
|
||||
/**
|
||||
* The File Type Task
|
||||
*
|
||||
* @var array
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected array $fileTypeTasks = [1 => 'image' , 2 => 'file' , 3 => 'media', 4 => 'file'];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Item $item The Item Class.
|
||||
* @param Items $items The Items Class.
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function __construct(Item $item, Items $items, )
|
||||
{
|
||||
$this->item = $item;
|
||||
$this->items = $items;
|
||||
$this->url = rtrim(Uri::root(), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file data that belong to this entity
|
||||
*
|
||||
* @param string $entity The entity guid
|
||||
* @param string $target The target entity name
|
||||
*
|
||||
* @return array|null
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function get(string $entity, string $target): ?array
|
||||
{
|
||||
if (($files = $this->items->table('file')->get([$entity], 'entity')) !== null)
|
||||
{
|
||||
foreach ($files as $n => $file)
|
||||
{
|
||||
if ($file->entity_type !== $target)
|
||||
{
|
||||
unset($files[$n]);
|
||||
continue;
|
||||
}
|
||||
$this->setFileTypeTask($file);
|
||||
$this->setFileTypeName($file);
|
||||
$this->setFileDownloadLink($file);
|
||||
}
|
||||
|
||||
// If the $files array is empty, return null
|
||||
return !empty($files) ? $files : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the file type name to this file
|
||||
*
|
||||
* @param object $file The file being updated
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function setFileTypeName(object &$file): void
|
||||
{
|
||||
if (($fileType = $this->getFileType($file->file_type ?? null)) !== null)
|
||||
{
|
||||
$file->type_name = $fileType->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
$file->type_name = 'error';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the file type task to this file
|
||||
*
|
||||
* @param object $file The file being updated
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function setFileTypeTask(object &$file): void
|
||||
{
|
||||
if (($fileType = $this->getFileType($file->file_type ?? null)) !== null)
|
||||
{
|
||||
$file->task = $this->getFileTypeTask($fileType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the file download link
|
||||
*
|
||||
* @param object $file The file being updated
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function setFileDownloadLink(object &$file): void
|
||||
{
|
||||
if (isset($file->task))
|
||||
{
|
||||
// Build the query parameters
|
||||
$queryParams = [
|
||||
'option' => 'com_componentbuilder',
|
||||
'controller' => 'download',
|
||||
'task' => 'download.' . $file->task,
|
||||
'file' => $file->guid,
|
||||
'name' => $file->name
|
||||
];
|
||||
|
||||
// Build the full URL
|
||||
$file->link = $this->url . Route::_('index.php?' . http_build_query($queryParams));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the file type task name
|
||||
*
|
||||
* @param object $data The type data array
|
||||
*
|
||||
* @return string The field name
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getFileTypeTask(object $data): string
|
||||
{
|
||||
$type = $data->type ?? 4;
|
||||
if (isset($this->fileTypeTasks[$type]))
|
||||
{
|
||||
return $this->fileTypeTasks[$type];
|
||||
}
|
||||
return 'file';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the file type details
|
||||
*
|
||||
* @param string|null $guid The GUID (Globally Unique Identifier) used as the key to retrieve the file type.
|
||||
*
|
||||
* @return object|null The item object if found, or null if the item does not exist.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getFileType(?string $guid): ?object
|
||||
{
|
||||
if ($guid === null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($this->fileTypes[$guid]))
|
||||
{
|
||||
return $this->fileTypes[$guid];
|
||||
}
|
||||
|
||||
$this->fileTypes[$guid] = $this->item->table('file_type')->get($guid);
|
||||
|
||||
return $this->fileTypes[$guid];
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 4th September, 2022
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Componentbuilder\File;
|
||||
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use VDM\Joomla\Service\Table;
|
||||
use VDM\Joomla\Service\Database;
|
||||
use VDM\Joomla\Service\Model;
|
||||
use VDM\Joomla\Service\Data;
|
||||
use VDM\Joomla\Componentbuilder\File\Service\File;
|
||||
use VDM\Joomla\Interfaces\FactoryInterface;
|
||||
use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
|
||||
|
||||
|
||||
/**
|
||||
* File Factory
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
abstract class Factory extends ExtendingFactory implements FactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a container object
|
||||
*
|
||||
* @return Container
|
||||
* @since 3.2.2
|
||||
*/
|
||||
protected static function createContainer(): Container
|
||||
{
|
||||
return (new Container())
|
||||
->registerServiceProvider(new Table())
|
||||
->registerServiceProvider(new Database())
|
||||
->registerServiceProvider(new Model())
|
||||
->registerServiceProvider(new Data())
|
||||
->registerServiceProvider(new File());
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 3rd September, 2020
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Componentbuilder\File;
|
||||
|
||||
|
||||
use VDM\Joomla\Utilities\UploadHelper;
|
||||
|
||||
|
||||
/**
|
||||
* File Handler Class
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
final class Handler extends UploadHelper
|
||||
{
|
||||
/**
|
||||
* Set the $useStreams property to use streams for file handling
|
||||
*
|
||||
* @param bool $useStreams True to use streams, false otherwise.
|
||||
*
|
||||
* @return self Returns the current instance to allow for method chaining.
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function setUseStreams(bool $useStreams): self
|
||||
{
|
||||
static::$useStreams = $useStreams;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $allowUnsafe property to allow or disallow unsafe file uploads.
|
||||
*
|
||||
* @param bool $allowUnsafe True to allow unsafe file uploads, false otherwise.
|
||||
*
|
||||
* @return self Returns the current instance to allow for method chaining.
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function setAllowUnsafe(bool $allowUnsafe): self
|
||||
{
|
||||
static::$allowUnsafe = $allowUnsafe;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $safeFileOptions property to define options for file safety checks.
|
||||
*
|
||||
* @param array $safeFileOptions An array of options for InputFilter::isSafeFile.
|
||||
*
|
||||
* @return self Returns the current instance to allow for method chaining.
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function setSafeFileOptions(array $safeFileOptions): self
|
||||
{
|
||||
static::$safeFileOptions = $safeFileOptions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $enqueueError property to control error reporting behavior.
|
||||
*
|
||||
* @param bool $enqueueError True to enqueue error messages, false to store them in the internal error array.
|
||||
*
|
||||
* @return self Returns the current instance to allow for method chaining.
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function setEnqueueError(bool $enqueueError): self
|
||||
{
|
||||
static::$enqueueError = $enqueueError;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $legalFormats property to define legal file formats.
|
||||
*
|
||||
* @param array $legalFormats An array of allowed file formats (e.g., ['jpg', 'png']).
|
||||
*
|
||||
* @return self Returns the current instance to allow for method chaining.
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function setLegalFormats(array $legalFormats): self
|
||||
{
|
||||
static::$legalFormats = $legalFormats;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a file from the input based on field name and file type, then process it.
|
||||
*
|
||||
* @param string $field The input field name for the file upload.
|
||||
* @param string $type The type of file (e.g., 'image', 'document').
|
||||
* @param string|null $filter The filter to apply when uploading the file.
|
||||
* @param string|null $path The directory path where the file should be saved.
|
||||
*
|
||||
* @return array|null File details or false on failure.
|
||||
* @since 3.0.11
|
||||
*/
|
||||
public function getFile(string $field, string $type, string $filter = null, string $path = null): ?array
|
||||
{
|
||||
return static::get($field, $type, $filter, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error messages as a string.
|
||||
*
|
||||
* @param bool $toString The option to return errors as a string
|
||||
*
|
||||
* @return string|array Returns the error messages as a single concatenated string.
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function getErrors(bool $toString = true): string|array
|
||||
{
|
||||
return static::getError($toString);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 3rd September, 2020
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Componentbuilder\File;
|
||||
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Filesystem\File;
|
||||
use VDM\Joomla\Interfaces\Data\ItemInterface as Item;
|
||||
use VDM\Joomla\Interfaces\Data\ItemsInterface as Items;
|
||||
use VDM\Joomla\Data\Guid;
|
||||
use VDM\Joomla\Componentbuilder\File\Type;
|
||||
use VDM\Joomla\Componentbuilder\File\Handler;
|
||||
use VDM\Joomla\Utilities\MimeHelper;
|
||||
|
||||
|
||||
/**
|
||||
* File Manager Class
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
final class Manager
|
||||
{
|
||||
/**
|
||||
* The Globally Unique Identifier.
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
use Guid;
|
||||
|
||||
/**
|
||||
* The Item Class.
|
||||
*
|
||||
* @var Item
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected Item $item;
|
||||
|
||||
/**
|
||||
* The Items Class.
|
||||
*
|
||||
* @var Items
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected Items $items;
|
||||
|
||||
/**
|
||||
* The Type Class.
|
||||
*
|
||||
* @var Type
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected Type $type;
|
||||
|
||||
/**
|
||||
* The Handler Class.
|
||||
*
|
||||
* @var Handler
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected Handler $handler;
|
||||
|
||||
/**
|
||||
* The active user
|
||||
*
|
||||
* @var User
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected User $user;
|
||||
|
||||
/**
|
||||
* Table Name
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected string $table = 'file';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Item $item The Item Class.
|
||||
* @param Items $items The Items Class.
|
||||
* @param Type $type The Type Class.
|
||||
* @param Handler $handler The Handler Class.
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function __construct(Item $item, Items $items, Type $type, Handler $handler)
|
||||
{
|
||||
$this->item = $item;
|
||||
$this->items = $items;
|
||||
$this->type = $type;
|
||||
$this->handler = $handler;
|
||||
$this->user = Factory::getApplication()->getIdentity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file, of a given file type and link it to an entity.
|
||||
*
|
||||
* @param string $guid The file type guid
|
||||
* @param string $entity The entity guid
|
||||
* @param string $target The target entity name
|
||||
*
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException If the file type is not valid.
|
||||
* @throws \RuntimeException If there is an error during file upload.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function upload(string $guid, string $entity, string $target): void
|
||||
{
|
||||
if (($fileType = $this->type->load($guid, $target)) === null)
|
||||
{
|
||||
throw new \InvalidArgumentException(Text::sprintf('COM_COMPONENTBUILDER_FILE_TYPE_NOT_VALID_IN_S_AREA', $target));
|
||||
}
|
||||
|
||||
// make sure the user have permissions to upload this file type
|
||||
if (!in_array($fileType['access'], $this->user->getAuthorisedViewLevels()))
|
||||
{
|
||||
throw new \InvalidArgumentException(Text::sprintf('COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSIONS_TO_UPLOAD_S', $fileType['name']));
|
||||
}
|
||||
|
||||
$details = $this->handler
|
||||
->setEnqueueError(false)
|
||||
->setLegalFormats($fileType['formats'])
|
||||
->getFile(
|
||||
$fileType['field'], // The input field name
|
||||
$fileType['type'], // The file type
|
||||
$fileType['filter'], // The filter to use when uploading the file
|
||||
$fileType['path'] // The path to the directory where the file must be placed
|
||||
);
|
||||
|
||||
if ($details === null)
|
||||
{
|
||||
// Throw an exception if file details couldn't be retrieved
|
||||
throw new \RuntimeException($this->handler->getErrors());
|
||||
}
|
||||
|
||||
// we might need to crop images
|
||||
if ($fileType['type'] === 'image')
|
||||
{
|
||||
// $this->cropImage($details, $guid);
|
||||
}
|
||||
|
||||
// store file in the file table
|
||||
$this->item->table($this->getTable())->set(
|
||||
$this->modelFileDetails($details, $guid, $entity, $target, $fileType)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file details for download
|
||||
*
|
||||
* @param string $guid The file guid
|
||||
*
|
||||
* @return array|null
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function download(string $guid): ?array
|
||||
{
|
||||
if (($file = $this->item->table($this->getTable())->get($guid)) !== null &&
|
||||
in_array($file->access, $this->user->getAuthorisedViewLevels()))
|
||||
{
|
||||
return (array) $file;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file.
|
||||
*
|
||||
* @param string $guid The file guid
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function delete(string $guid): void
|
||||
{
|
||||
if (($file = $this->item->table($this->getTable())->get($guid)) !== null &&
|
||||
in_array($file->access, $this->user->getAuthorisedViewLevels()))
|
||||
{
|
||||
$this->item->table($this->getTable())->delete($guid); // from DB
|
||||
|
||||
if (is_file($file->file_path) && is_writable($file->file_path))
|
||||
{
|
||||
File::delete($file->file_path); // from file system
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current active table
|
||||
*
|
||||
* @param string $table The table that should be active
|
||||
*
|
||||
* @return self
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function table(string $table): self
|
||||
{
|
||||
$this->table = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current active table
|
||||
*
|
||||
* @return string
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* model the file details to store in the file table
|
||||
*
|
||||
* @param array $details The uploaded file details.
|
||||
* @param string $guid The file type guid
|
||||
* @param string $entity The entity guid
|
||||
* @param string $target The target entity name
|
||||
* @param array $fileType The file type
|
||||
*
|
||||
* @return object
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function modelFileDetails(array $details, string $guid, string $entity, string $target, array $fileType): object
|
||||
{
|
||||
return (object) [
|
||||
'name' => $details['name'],
|
||||
'file_type' => $guid,
|
||||
'extension' => $details['extension'] ?? 'error',
|
||||
'size' => $details['size'] ?? 0,
|
||||
'mime' => $details['mime'] ?? '',
|
||||
'file_path' => $details['full_path'],
|
||||
'entity_type' => $target,
|
||||
'entity' => $entity,
|
||||
'access' => $fileType['download_access'] ?? 1,
|
||||
'guid' => $this->getGuid('guid'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 4th September, 2022
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Componentbuilder\File\Service;
|
||||
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\File\Type;
|
||||
use VDM\Joomla\Componentbuilder\File\Handler;
|
||||
use VDM\Joomla\Componentbuilder\File\Manager;
|
||||
use VDM\Joomla\Componentbuilder\File\Display;
|
||||
|
||||
|
||||
/**
|
||||
* File Service Provider
|
||||
*
|
||||
* @since 5.0.3
|
||||
*/
|
||||
class File implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->alias(Type::class, 'File.Type')
|
||||
->share('File.Type', [$this, 'getType'], true);
|
||||
|
||||
$container->alias(Handler::class, 'File.Handler')
|
||||
->share('File.Handler', [$this, 'getHandler'], true);
|
||||
|
||||
$container->alias(Manager::class, 'File.Manager')
|
||||
->share('File.Manager', [$this, 'getManager'], true);
|
||||
|
||||
$container->alias(Display::class, 'File.Display')
|
||||
->share('File.Display', [$this, 'getDisplay'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Type Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Type
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function getType(Container $container): Type
|
||||
{
|
||||
return new Type(
|
||||
$container->get('Data.Item')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Handler Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Handler
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function getHandler(Container $container): Handler
|
||||
{
|
||||
return new Handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Manager Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Manager
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function getManager(Container $container): Manager
|
||||
{
|
||||
return new Manager(
|
||||
$container->get('Data.Item'),
|
||||
$container->get('Data.Items'),
|
||||
$container->get('File.Type'),
|
||||
$container->get('File.Handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Display Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Display
|
||||
* @since 5.0.3
|
||||
*/
|
||||
public function getDisplay(Container $container): Display
|
||||
{
|
||||
return new Display(
|
||||
$container->get('Data.Item'),
|
||||
$container->get('Data.Items')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
@@ -0,0 +1,301 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 3rd September, 2020
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Componentbuilder\File;
|
||||
|
||||
|
||||
use Joomla\Filesystem\Path;
|
||||
use VDM\Joomla\Interfaces\Data\ItemInterface as Item;
|
||||
|
||||
|
||||
/**
|
||||
* File Type Class
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
final class Type
|
||||
{
|
||||
/**
|
||||
* The Item Class.
|
||||
*
|
||||
* @var Item
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected Item $item;
|
||||
|
||||
/**
|
||||
* The File Types
|
||||
*
|
||||
* @var array
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected array $fileTypes = [1 => 'image' , 2 => 'document' , 3 => 'media', 4 => 'file'];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Item $item The Item Class.
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function __construct(Item $item)
|
||||
{
|
||||
$this->item = $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the file type details (ajax)
|
||||
*
|
||||
* @param string $guid The GUID (Globally Unique Identifier) used as the key to retrieve the file type
|
||||
* @param string $target The entity target name.
|
||||
*
|
||||
* @return array|null The item object if found, or null if the item does not exist.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function get(string $guid, string $target): ?array
|
||||
{
|
||||
if (($fileType = $this->details($guid)) !== null &&
|
||||
$this->validTarget($fileType, $target))
|
||||
{
|
||||
return [
|
||||
'name' => $this->getFieldName($fileType),
|
||||
'allow' => $this->getAllow($fileType),
|
||||
'allow_span' => $this->getAllowSpan($fileType),
|
||||
'file_type_span' => $fileType->name ?? 'file',
|
||||
'display_fields' => $fileType->display_fields ?? null,
|
||||
'param_fields' => $fileType->param_fields ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the file type details (upload)
|
||||
*
|
||||
* @param string $guid The GUID (Globally Unique Identifier) used as the key to retrieve the file type
|
||||
* @param string $target The entity target name.
|
||||
*
|
||||
* @return array|null The item object if found, or null if the item does not exist.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function load(string $guid, string $target): ?array
|
||||
{
|
||||
if (($fileType = $this->details($guid)) !== null &&
|
||||
$this->validTarget($fileType, $target))
|
||||
{
|
||||
return [
|
||||
'name' => $fileType->name ?? 'files',
|
||||
'access' => $fileType->access ?? 1,
|
||||
'download_access' => $fileType->download_access ?? 1,
|
||||
'field' => $this->getFieldName($fileType),
|
||||
'type' => $this->getFieldName($fileType),
|
||||
'formats' => $this->getAllowFormats($fileType) ?? [],
|
||||
'filter' => $fileType->filter ?? null,
|
||||
'path' => $this->getFileTypePath($fileType)
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the file type details
|
||||
*
|
||||
* @param string $guid The GUID (Globally Unique Identifier) used as the key to retrieve the file type.
|
||||
*
|
||||
* @return object|null The item object if found, or null if the item does not exist.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public function details(string $guid): ?object
|
||||
{
|
||||
return $this->item->table('file_type')->get($guid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Valid if this is a correct target trying to call this file type
|
||||
*
|
||||
* @param object $data The type data array
|
||||
* @param string $target The entity target name.
|
||||
*
|
||||
* @return bool True if valid target
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function validTarget(object $data, string $target): bool
|
||||
{
|
||||
$targets = $data->target ?? null;
|
||||
if (!empty($targets))
|
||||
{
|
||||
$targets = (array) $targets;
|
||||
return in_array($target, $targets);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the field name
|
||||
*
|
||||
* @param object $data The type data array
|
||||
*
|
||||
* @return string The field name
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getFieldName(object $data): string
|
||||
{
|
||||
$type = $data->type ?? 4;
|
||||
if (isset($this->fileTypes[$type]))
|
||||
{
|
||||
return $this->fileTypes[$type];
|
||||
}
|
||||
return 'file';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the allow formats (for script)
|
||||
*
|
||||
* @param object $data The type data array
|
||||
*
|
||||
* @return string The allow values
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getAllow(object $data): string
|
||||
{
|
||||
$formats = $this->getAllowFormats($data);
|
||||
if (!empty($formats))
|
||||
{
|
||||
return '*.(' . implode('|', $formats) . ')';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the allow formats (for span)
|
||||
*
|
||||
* @param object $data The type data array
|
||||
*
|
||||
* @return string The allow values
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getAllowSpan(object $data): string
|
||||
{
|
||||
$formats = $this->getAllowFormats($data);
|
||||
if (!empty($formats))
|
||||
{
|
||||
return '(formats allowed: <b>' . implode(', ', $formats) . '</b>)';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the allow formats
|
||||
*
|
||||
* @param object|null $data The type data array
|
||||
*
|
||||
* @return array|null The allow values
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getAllowFormats(object $data): ?array
|
||||
{
|
||||
$type = $data->type ?? 4;
|
||||
switch ($type)
|
||||
{
|
||||
case 1:
|
||||
$formats = $data->image_formats ?? null;
|
||||
break;
|
||||
case 2:
|
||||
$formats = $data->document_formats ?? null;
|
||||
break;
|
||||
case 3:
|
||||
$formats = $data->media_formats ?? null;
|
||||
break;
|
||||
default:
|
||||
$formats = $data->file_formats ?? null;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($formats)
|
||||
{
|
||||
return (array) $formats;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the file type path based on provided data.
|
||||
*
|
||||
* Performs safety checks and returns either a cleaned path if it exists
|
||||
* and is a writable directory, or constructs a relative path to the 'images' folder
|
||||
* based on the last folder name from the given path.
|
||||
*
|
||||
* @param object $data The type data object containing path information.
|
||||
*
|
||||
* @return string|null Returns the cleaned file path or null if no valid path is found.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getFileTypePath(object $data): ?string
|
||||
{
|
||||
// Validate the provided path data
|
||||
$path = isset($data->path) && is_string($data->path) && trim($data->path) !== '' ?
|
||||
Path::clean(trim($data->path)) : null;
|
||||
|
||||
// Return the path if it's a valid directory and writable
|
||||
if ($path !== null && is_dir($path) && is_writable($path))
|
||||
{
|
||||
return $path;
|
||||
}
|
||||
|
||||
// If no valid path is found, try to derive a relative path from the 'images' folder
|
||||
if ($path !== null && ($folder = $this->getLastFolderName($path)) !== null)
|
||||
{
|
||||
return JPATH_SITE . '/images/' . $folder;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively retrieves the last folder name from a given path, ignoring any file names.
|
||||
* If the last part of the path contains a dot (indicating a file), it moves up the directory tree
|
||||
* until it finds a valid folder name. Returns null if no valid folder is found.
|
||||
*
|
||||
* @param string $path The file system path from which to extract the last folder name.
|
||||
*
|
||||
* @return string|null Returns the last folder name if found, or null if no valid folder exists.
|
||||
* @since 5.0.2
|
||||
*/
|
||||
protected function getLastFolderName(string $path): ?string
|
||||
{
|
||||
// Remove any trailing slashes to avoid an empty result
|
||||
$path = rtrim($path, '/\\');
|
||||
|
||||
// If the path becomes empty, return null (base case)
|
||||
if (empty($path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the last part of the path
|
||||
$lastPart = basename($path);
|
||||
|
||||
// If the last part contains a dot (and it's not a hidden folder), move up the directory tree
|
||||
if (strpos($lastPart, '.') > 0)
|
||||
{
|
||||
// If it contains a dot, treat it as a file and move up one level
|
||||
return $this->getLastFolderName(dirname($path));
|
||||
}
|
||||
|
||||
// Return the last folder name (if it's valid and not a file)
|
||||
return $lastPart;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
Reference in New Issue
Block a user