Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
49 changes: 10 additions & 39 deletions build/media_source/system/js/fields/joomla-image-select.w-c.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,35 +68,6 @@
: o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === 'string'
);

/**
* Method to safely append parameters to a URL string
*
* @param url {string} The URL
* @param key {string} The key of the parameter
* @param value {string} The value of the parameter
*
* @returns {string}
*/
const appendParam = (url, key, value) => {
const newKey = encodeURIComponent(key);
const newValue = encodeURIComponent(value);
const r = new RegExp(`(&|\\?)${key}=[^&]*`);
let s = url;
const param = `${newKey}=${newValue}`;

s = s.replace(r, `$1${param}`);

if (!RegExp.$1 && s.includes('?')) {
return `${s}&${param}`;
}

if (!RegExp.$1 && !s.includes('?')) {
return `${s}?${param}`;
}

return s;
};

/**
* Method to append the image in an editor or a field
*
Expand All @@ -106,19 +77,20 @@
*/
const execTransform = (resp, editor, fieldClass) => {
if (resp.success === true) {
if (resp.data[0].url) {
if (/local-/.test(resp.data[0].adapter)) {
const media = resp.data[0];
if (media.url) {
if (/local-/.test(media.adapter)) {
const { rootFull } = Joomla.getOptions('system.paths');

// eslint-disable-next-line prefer-destructuring
Joomla.selectedMediaFile.url = resp.data[0].url.split(rootFull)[1];
if (resp.data[0].thumb_path) {
Joomla.selectedMediaFile.thumb = resp.data[0].thumb_path;
Joomla.selectedMediaFile.url = media.url.split(rootFull)[1];
if (media.thumb_path) {
Joomla.selectedMediaFile.thumb = media.thumb_path;
} else {
Joomla.selectedMediaFile.thumb = false;
}
} else if (resp.data[0].thumb_path) {
Joomla.selectedMediaFile.thumb = resp.data[0].thumb_path;
} else if (media.thumb_path) {
Joomla.selectedMediaFile.url = media.url;
Joomla.selectedMediaFile.thumb = media.thumb_path;
}
} else {
Joomla.selectedMediaFile.url = false;
Expand Down Expand Up @@ -162,8 +134,7 @@

Joomla.editors.instances[editor].replaceSelection(imageElement);
} else {
const val = appendParam(Joomla.selectedMediaFile.url, 'joomla_image_width', Joomla.selectedMediaFile.width);
editor.value = appendParam(val, 'joomla_image_height', Joomla.selectedMediaFile.height);
editor.value = `${Joomla.selectedMediaFile.url}#joomlaImage://${media.path.replace(':', '')}?width=${Joomla.selectedMediaFile.width}&height=${Joomla.selectedMediaFile.height}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

${media.path.replace(':', '')}

That doesn't look right, the path (after the adapter /) should be url encoded. please don't remove parts of the string

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it's needed so that the value has format which we discussed. media.path contains adapter name, :, and then path to the file, so I need to remove : from there to make it works.

Sample data of media.path: local-0:/sampledata/cassiopeia/nasa1-400.jpg

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok that makes sense at least for the first parameter should be removed, a second : shouldnt be a problem (after the /)

fieldClass.updatePreview();
}
}
Expand Down
4 changes: 2 additions & 2 deletions layouts/joomla/form/field/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@
}

// The url for the modal
$url = ($readonly ? ''
$url = ($readonly ? ''
: ($link ?: 'index.php?option=com_media&view=media&tmpl=component&asset='
. $asset . '&author=' . $authorId)
. '&fieldid={field-media-id}&path=local-images:/' . $folder);
. '&fieldid={field-media-id}&path=' . $folder);

// Correctly route the url to ensure it's correctly using sef modes and subfolders
$url = Route::_($url);
Expand Down
68 changes: 62 additions & 6 deletions libraries/src/Form/Field/MediaField.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormField;
use Joomla\CMS\Helper\MediaHelper;
use Joomla\CMS\Uri\Uri;

/**
* Provides a modal media selector including upload mechanism
Expand Down Expand Up @@ -250,15 +252,69 @@ public function getLayoutData()
$asset = Factory::getApplication()->input->get('option');
}

if ($this->value && is_file(JPATH_ROOT . '/' . $this->value))
// Value in new format such as images/headers/blue-flower.jpg#joomlaImage://local-images/headers/blue-flower.jpg?width=700&height=180
if ($this->value && strpos($this->value, '#') !== false)
{
$this->folder = explode('/', $this->value);
$this->folder = array_diff_assoc($this->folder, explode('/', ComponentHelper::getParams('com_media')->get('image_path', 'images')));
array_pop($this->folder);
$this->folder = implode('/', $this->folder);
$uri = new Uri(explode('#', $this->value)[1]);
$adapter = $uri->getHost();
$path = $uri->getPath();

// Remove filename from stored path to get the path to the folder which file is stored
$pos = strrpos($path, '/');

if ($pos !== false)
{
$path = substr($path, 0, $pos);
}

if ($path === '')
{
$path = '/';
}

$this->folder = $adapter . ':' . $path;
}
elseif ($this->value && is_file(JPATH_ROOT . '/' . $this->value))
{
/**
* Local image, for example images/sampledata/cassiopeia/nasa2-640.jpg . We need to validate and make sure
* the top level folder is one of the directory configured in filesystem local plugin to avoid error message
* displayed in manage when users click on Select button to select a new image
*/
$paths = explode('/', $this->value);

// Remove filename from $paths array
array_pop($paths);

if (MediaHelper::isValidLocalDirectory($paths[0]))
{
$adapterName = array_shift($paths);
$this->folder = 'local-' . $adapterName . ':/' . implode('/', $paths);
}
}
elseif ($this->directory && is_dir(JPATH_ROOT . '/' . ComponentHelper::getParams('com_media')->get('image_path', 'images') . '/' . $this->directory))
{
/**
* This is the case where a folder is configured in directory attribute of the form field. The directory needs
* to be a relative folder of the folder configured in Path to Images Folder config option of Media component.
* Same with a already stored local image above, we need to validate and make sure top level folder is one of the directory
* configured in filesystem local plugin
*/
$path = ComponentHelper::getParams('com_media')->get('image_path', 'images') . '/' . $this->directory;
$paths = explode('/', $path);

if (MediaHelper::isValidLocalDirectory($paths[0]))
{
$adapterName = array_shift($paths);
$this->folder = 'local-' . $adapterName . '/' . implode('/', $paths);
}
}
elseif (is_dir(JPATH_ROOT . '/' . ComponentHelper::getParams('com_media')->get('image_path', 'images') . '/' . $this->directory))
elseif ($this->directory && strpos(':', $this->directory))
{
/**
* Directory contains adapter information and path, for example via programming or directly defined in xml
* via directory attribute
*/
$this->folder = $this->directory;
}
else
Expand Down
55 changes: 30 additions & 25 deletions libraries/src/HTML/HTMLHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -684,40 +684,45 @@ public static function cleanImageURL($url)
return $obj;
}

$url = preg_replace('#&#', '&', $url);
$pieces = explode('?', $url);
$mediaUri = new Uri($url);

parse_str($pieces[1], $urlParams);

if (isset($urlParams['joomla_image_height']) && $urlParams['joomla_image_height'] !== 'null')
// Old image URL format
if ($mediaUri->hasVar('joomla_image_height'))
{
if ((int) $urlParams['joomla_image_height'] > 0)
{
$obj->attributes['height'] = $urlParams['joomla_image_height'];
}
else
{
unset($obj->attributes['height']);
}
$height = (int) $mediaUri->getVar('joomla_image_height');
$width = (int) $mediaUri->getVar('joomla_image_width');

unset($urlParams['joomla_image_height']);
$mediaUri->delVar('joomla_image_height');
$mediaUri->delVar('joomla_image_width');
}
else
{
// New Image URL format
$fragmentUri = new Uri($mediaUri->getFragment());
$width = (int) $fragmentUri->getVar('width', 0);
$height = (int) $fragmentUri->getVar('height', 0);
}

if (isset($urlParams['joomla_image_width']) && $urlParams['joomla_image_width'] !== 'null')
if ($width > 0)
{
if ((int) $urlParams['joomla_image_width'] > 0)
{
$obj->attributes['width'] = $urlParams['joomla_image_width'];
}
else
{
unset($obj->attributes['width']);
}
$obj->attributes['width'] = $width;
}
else
{
unset($obj->attributes['width']);
}

unset($urlParams['joomla_image_width']);
if ($height > 0)
{
$obj->attributes['height'] = $height;
}
else
{
unset($obj->attributes['height']);
}

$obj->url = $pieces[0] . (count($urlParams) ? '?' . http_build_query($urlParams) : '');
$mediaUri->setFragment('');
$obj->url = $mediaUri->toString();

return $obj;
}
Expand Down
40 changes: 40 additions & 0 deletions libraries/src/Helper/MediaHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Registry\Registry;

/**
* Media helper class
Expand Down Expand Up @@ -422,4 +424,42 @@ public function toBytes($val)
return $val;
}
}

/**
* Method to check if the given directory is a directory configured in FileSystem - Local plugin
*
* @param string $directory
*
* @return boolean
*
* @since __DEPLOY_VERSION__
*/
public static function isValidLocalDirectory($directory)
{
$plugin = PluginHelper::getPlugin('filesystem', 'local');

if ($plugin)
{
$params = new Registry($plugin->params);

$directories = $params->get('directories', '[{"directory": "images"}]');

// Do a check if default settings are not saved by user
// If not initialize them manually
if (is_string($directories))
{
$directories = json_decode($directories);
}

foreach ($directories as $directoryEntity)
{
if ($directoryEntity->directory === $directory)
{
return true;
}
}
}

return false;
}
}