441 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			441 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| /**
 | |
|  * @package         Advanced Custom Fields
 | |
|  * @version         2.8.8 Pro
 | |
|  * 
 | |
|  * @author          Tassos Marinos <info@tassos.gr>
 | |
|  * @link            http://www.tassos.gr
 | |
|  * @copyright       Copyright © 2019 Tassos Marinos All Rights Reserved
 | |
|  * @license         GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
 | |
| */
 | |
| 
 | |
| defined('_JEXEC') or die;
 | |
| 
 | |
| use NRFramework\Helpers\Widgets\GalleryManager;
 | |
| use NRFramework\Functions;
 | |
| use Joomla\Registry\Registry;
 | |
| use Joomla\CMS\Factory;
 | |
| use Joomla\CMS\MVC\Model\BaseDatabaseModel;
 | |
| use Joomla\CMS\HTML\HTMLHelper;
 | |
| use Joomla\CMS\Utility\Utility;
 | |
| use Joomla\CMS\Language\Text;
 | |
| 
 | |
| JLoader::register('ACF_Field', JPATH_PLUGINS . '/system/acf/helper/plugin.php');
 | |
| JLoader::register('ACFGalleryHelper', __DIR__ . '/fields/helper.php');
 | |
| 
 | |
| if (!class_exists('ACF_Field'))
 | |
| {
 | |
| 	Factory::getApplication()->enqueueMessage('Advanced Custom Fields System Plugin is missing', 'error');
 | |
| 	return;
 | |
| }
 | |
| 
 | |
| class PlgFieldsACFGallery extends ACF_Field
 | |
| {
 | |
| 	/**
 | |
| 	 *  The validation rule will be used to validate the field on saving
 | |
| 	 *
 | |
| 	 *  @var  string
 | |
| 	 */
 | |
| 	protected $validate = 'acfrequired';
 | |
| 
 | |
|     public function onUserAfterSave($user, $isnew, $success, $msg)
 | |
|     {
 | |
|         // Load Fields Component Helper class
 | |
| 		JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
 | |
| 
 | |
| 		$fields = FieldsHelper::getFields('com_users.user', $user, true);
 | |
| 
 | |
| 		if (!$fields)
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 		
 | |
| 		// Get the fields data
 | |
| 		$fieldsData = !empty($user['com_fields']) ? $user['com_fields'] : [];
 | |
| 
 | |
| 		$this->processFiles($fields, $fieldsData, (object) $user);
 | |
| 	}
 | |
| 
 | |
| 	public function onContentAfterSave($context, $item, $isNew, $data = [])
 | |
| 	{
 | |
| 		if (!is_array($data))
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 		
 | |
| 		if (!isset($data['com_fields']))
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 		
 | |
| 		// Create correct context for category
 | |
| 		if ($context == 'com_categories.category')
 | |
| 		{
 | |
| 			$context = $item->get('extension') . '.categories';
 | |
| 		}
 | |
| 
 | |
|         // Load Fields Component Helper class
 | |
| 		JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
 | |
| 
 | |
| 		// Check the context
 | |
| 		$parts = FieldsHelper::extract($context, $item);
 | |
| 
 | |
| 		if (!$parts)
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Compile the right context for the fields
 | |
| 		$context = $parts[0] . '.' . $parts[1];
 | |
| 
 | |
| 		// Loading the fields
 | |
| 		$fields = FieldsHelper::getFields($context, $item);
 | |
| 
 | |
| 		if (!$fields)
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		// Get the fields data
 | |
| 		$fieldsData = !empty($data['com_fields']) ? $data['com_fields'] : [];
 | |
| 
 | |
| 		$this->processFiles($fields, $fieldsData, $item);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Processes the files.
 | |
| 	 * 
 | |
| 	 * Either duplicates the files or uploads them to final directory.
 | |
| 	 * 
 | |
| 	 * @param   array   $fields
 | |
| 	 * @param   array   $fieldsData
 | |
| 	 * @param   object  $item
 | |
| 	 * 
 | |
| 	 * @return  void
 | |
| 	 */
 | |
| 	private function processFiles($fields = [], $fieldsData = [], $item = [])
 | |
| 	{
 | |
| 		if (!$fields || !$fieldsData || !$item)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// Whether we should clean up the temp folder at the end of this process
 | |
| 		$should_clean = false;
 | |
| 
 | |
| 		// Get the Fields Model
 | |
|         if (!defined('nrJ4'))
 | |
| 		{
 | |
| 			$model = JModelLegacy::getInstance('Field', 'FieldsModel', ['ignore_request' => true]);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$model = Factory::getApplication()->bootComponent('com_fields')->getMVCFactory()->createModel('Field', 'Administrator', ['ignore_request' => true]);
 | |
| 		}
 | |
| 
 | |
| 		// Cache subform fields
 | |
| 		$subform_fields = [];
 | |
| 
 | |
| 		// Loop over the fields
 | |
| 		foreach ($fields as $field)
 | |
| 		{
 | |
| 			$field_type = $field->type;
 | |
| 			
 | |
| 			/**
 | |
| 			 * Check whether a Gallery field is used within the Subform field.
 | |
| 			 */
 | |
| 			if ($field_type === 'subform')
 | |
| 			{
 | |
| 				$submitted_subform_value = array_key_exists($field->name, $fieldsData) ? $fieldsData[$field->name] : null;
 | |
| 
 | |
| 				// Ensure it has a value
 | |
| 				if (!$submitted_subform_value || !$subform_value = json_decode($field->rawvalue, true))
 | |
| 				{
 | |
| 					// Update subform field
 | |
| 					$model->setFieldValue($field->id, $item->id, json_encode([]));
 | |
| 					
 | |
| 					continue;
 | |
| 				}
 | |
| 
 | |
| 				$update = false;
 | |
| 				$is_subform_non_repeatable = false;
 | |
| 
 | |
| 				// Make non-repeatable subform fields a multi array so we can parse them
 | |
| 				if (Functions::startsWith(array_key_first($subform_value), 'field') && $field->fieldparams->get('repeat', '0') === '0')
 | |
| 				{
 | |
| 					$is_subform_non_repeatable = true;
 | |
| 					$subform_value = [$subform_value];
 | |
| 				}
 | |
| 
 | |
| 				foreach ($subform_value as $key => &$value)
 | |
| 				{
 | |
| 					foreach ($value as $_key => &$_value)
 | |
| 					{
 | |
| 						// Get Field ID
 | |
| 						$field_id = str_replace('field', '', $_key);
 | |
| 						
 | |
| 						// Get Field by ID
 | |
| 						$subform_field = isset($subform_fields[$field_id]) ? $subform_fields[$field_id] : $model->getItem($field_id);
 | |
| 
 | |
| 						// Only proceed for this field type
 | |
| 						if ($subform_field->type !== $this->_name)
 | |
| 						{
 | |
| 							continue;
 | |
| 						}
 | |
| 
 | |
| 						// Cache field
 | |
| 						if (!isset($subform_fields[$field_id]))
 | |
| 						{
 | |
| 							$subform_fields[$field_id] = $subform_field;
 | |
| 						}
 | |
| 
 | |
| 						// Check if value can be json_decoded
 | |
| 						if (is_string($_value))
 | |
| 						{
 | |
| 							if ($decoded = json_decode($_value, true))
 | |
| 							{
 | |
| 								$_value = $decoded;
 | |
| 							}
 | |
| 						}
 | |
| 
 | |
| 						// $_value is a string when batching an item
 | |
| 						if (!is_array($_value))
 | |
| 						{
 | |
| 							$_value = [];
 | |
| 						}
 | |
| 
 | |
| 						if (\ACF\Item::isCopying())
 | |
| 						{
 | |
| 							// Duplicate files
 | |
| 							ACFGalleryHelper::duplicateFiles($_value);
 | |
| 						}
 | |
| 						else
 | |
| 						{
 | |
| 							// We should run our cleanup routine at the end
 | |
| 							$should_clean = true;
 | |
| 	
 | |
| 							// Move to final folder
 | |
| 							$items = GalleryManager::moveTempItemsToDestination($_value, $subform_field, $this->getDestinationFolder($subform_field, $item));
 | |
| 
 | |
| 							// Save item tags
 | |
| 							$_value['items'] = GalleryManager::saveItemTags($items);
 | |
| 						}
 | |
| 
 | |
| 						$update = true;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				if ($update)
 | |
| 				{
 | |
| 					if ($is_subform_non_repeatable)
 | |
| 					{
 | |
| 						$subform_value = reset($subform_value);
 | |
| 					}
 | |
| 
 | |
| 					// Update subform field
 | |
| 					$model->setFieldValue($field->id, $item->id, json_encode($subform_value));
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				// Only proceed for this field type
 | |
| 				if ($field_type !== $this->_name)
 | |
| 				{
 | |
| 					continue;
 | |
| 				}
 | |
| 	
 | |
| 				// Determine the value if it is available from the data
 | |
| 				$value = array_key_exists($field->name, $fieldsData) ? $fieldsData[$field->name] : null;
 | |
| 	
 | |
| 				if (!$value)
 | |
| 				{
 | |
| 					continue;
 | |
| 				}
 | |
| 
 | |
| 				// Check if value can be json_decoded
 | |
| 				if (is_string($value))
 | |
| 				{
 | |
| 					if ($decoded = json_decode($value, true))
 | |
| 					{
 | |
| 						$value = $decoded;
 | |
| 					}
 | |
| 				}
 | |
| 	
 | |
| 				// $value is a string when batching an item
 | |
| 				if (!is_array($value))
 | |
| 				{
 | |
| 					$value = [];
 | |
| 				}
 | |
| 
 | |
| 				if (\ACF\Item::isCopying())
 | |
| 				{
 | |
| 					// Duplicate files
 | |
| 					ACFGalleryHelper::duplicateFiles($value);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					// We should run our cleanup routine at the end
 | |
| 					$should_clean = true;
 | |
| 	
 | |
| 					// Move to final folder
 | |
| 					$items = GalleryManager::moveTempItemsToDestination($value, $field, $this->getDestinationFolder($field, $item));
 | |
| 	
 | |
| 					// Save item tags
 | |
| 					$value['items'] = GalleryManager::saveItemTags($items);
 | |
| 				}
 | |
| 
 | |
| 				// Setting the value for the field and the item
 | |
| 				$model->setFieldValue($field->id, $item->id, json_encode($value));
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if ($should_clean)
 | |
| 		{
 | |
| 			// Clean old files from temp folder
 | |
| 			GalleryManager::clean();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns the destination folder.
 | |
| 	 * 
 | |
| 	 * @param   object  $field
 | |
| 	 * @param   array   $item
 | |
| 	 * 
 | |
| 	 * @return  string
 | |
| 	 */
 | |
| 	private function getDestinationFolder($field, $item)
 | |
| 	{
 | |
| 		$ds = DIRECTORY_SEPARATOR;
 | |
| 		$destination_folder = null;
 | |
| 
 | |
| 		$field_id = $field->id;
 | |
| 		$item_id = $item->id;
 | |
| 		
 | |
| 		// Make field params use Registry
 | |
| 		if (!$field->fieldparams instanceof Registry)
 | |
| 		{
 | |
| 			$field->fieldparams = new Registry($field->fieldparams);
 | |
| 		}
 | |
| 
 | |
| 		switch ($field->fieldparams->get('upload_folder_type', 'auto'))
 | |
| 		{
 | |
| 			case 'auto':
 | |
| 			default:
 | |
| 				// Get context and remove `com_` part
 | |
| 				$context = preg_replace('/^com_/', '', Factory::getApplication()->input->get('option'));
 | |
| 				$destination_folder = ['media', 'acfgallery', $context, $item_id, $field_id];
 | |
| 				break;
 | |
| 			case 'custom':
 | |
| 				$upload_folder = trim(ltrim($field->fieldparams->get('upload_folder'), $ds), $ds);
 | |
| 
 | |
| 				// Smart Tags Instance
 | |
| 				$st = new \NRFramework\SmartTags();
 | |
| 
 | |
| 				// Add custom Smart Tags
 | |
| 				$catAlias = isset($item->catid) ? $this->getCategoryAlias($item->catid) : '';
 | |
| 
 | |
| 				$custom_tags = [
 | |
| 					'field_id' => $field_id,
 | |
| 					'cat_id' => isset($item->catid) ? $item->catid : '',
 | |
| 					'cat_alias' => $catAlias,
 | |
| 					'item_catid' => isset($item->catid) ? $item->catid : '',
 | |
| 					'item_catalias' => $catAlias,
 | |
| 					'item_id' => $item_id,
 | |
| 					'item_alias' => isset($item->alias) ? $item->alias : '',
 | |
| 					'item_author_id' => isset($item->created_by) ? $item->created_by : ''
 | |
| 				];
 | |
| 				$st->add($custom_tags, 'field.');
 | |
| 
 | |
| 				// Replace Smart Tags
 | |
| 				$upload_folder = $st->replace($upload_folder);
 | |
| 
 | |
| 				$destination_folder = [$upload_folder];
 | |
| 				break;
 | |
| 		}
 | |
| 
 | |
| 		return implode($ds, array_merge([JPATH_ROOT], $destination_folder)) . $ds;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns a category alias by its ID.
 | |
| 	 * 
 | |
| 	 * @param   int     $cat_id
 | |
| 	 * 
 | |
| 	 * @return  string
 | |
| 	 */
 | |
| 	private function getCategoryAlias($cat_id = null)
 | |
| 	{
 | |
| 		if (!$cat_id)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 		
 | |
| 		$db = Factory::getDbo();
 | |
| 
 | |
| 		$query = $db->getQuery(true)
 | |
| 			->select($db->quoteName('alias'))
 | |
| 			->from($db->quoteName('#__categories'))
 | |
| 			->where($db->quoteName('id') . ' = ' . (int) $cat_id);
 | |
| 		$db->setQuery($query);
 | |
| 
 | |
| 		return $db->loadResult();
 | |
| 	}
 | |
| 
 | |
|     /**
 | |
| 	 * Transforms the field into a DOM XML element and appends it as a child on the given parent.
 | |
| 	 *
 | |
| 	 * @param   stdClass    $field   The field.
 | |
| 	 * @param   DOMElement  $parent  The field node parent.
 | |
| 	 * @param   Form        $form    The form.
 | |
| 	 *
 | |
| 	 * @return  DOMElement
 | |
| 	 *
 | |
| 	 * @since   3.7.0
 | |
| 	 */
 | |
| 	public function onCustomFieldsPrepareDom($field, DOMElement $parent, Joomla\CMS\Form\Form $form)
 | |
| 	{
 | |
| 		if (!$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form))
 | |
| 		{
 | |
| 			return $fieldNode;
 | |
|         }
 | |
|         
 | |
| 		$fieldNode->setAttribute('field_id', $field->id);
 | |
| 
 | |
| 		return $fieldNode;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * The form event. Load additional parameters when available into the field form.
 | |
| 	 * Only when the type of the form is of interest.
 | |
| 	 *
 | |
| 	 * @param   JForm     $form  The form
 | |
| 	 * @param   stdClass  $data  The data
 | |
| 	 *
 | |
| 	 * @return  void
 | |
| 	 */
 | |
| 	public function onContentPrepareForm(Joomla\CMS\Form\Form $form, $data)
 | |
| 	{
 | |
| 		// Make sure we are manipulating the right field.
 | |
| 		if (isset($data->type) && $data->type != $this->_name)
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		$result = parent::onContentPrepareForm($form, $data);
 | |
| 
 | |
| 		// Display the server's maximum upload size in the field's description
 | |
| 		$max_upload_size_str = HTMLHelper::_('number.bytes', Utility::getMaxUploadSize());
 | |
| 		$field_desc = $form->getFieldAttribute('max_file_size', 'description', null, 'fieldparams');
 | |
| 		$form->setFieldAttribute('max_file_size', 'description', Text::sprintf($field_desc, $max_upload_size_str), 'fieldparams');
 | |
| 		
 | |
| 		// Set the Field ID in Upload Folder Type description (if field is saved), otherwise, show FIELD_ID placeholder.
 | |
| 		// ITEM_ID is not replaceable in the field settings.
 | |
| 		$field_id = isset($data->id) ? $data->id : 'FIELD_ID';
 | |
| 		$upload_folder_type_desc = $form->getFieldAttribute('upload_folder_type', 'description', null, 'fieldparams');
 | |
| 		$form->setFieldAttribute('upload_folder_type', 'description', Text::sprintf($upload_folder_type_desc, $field_id), 'fieldparams');
 | |
| 
 | |
| 		return $result;
 | |
| 	}
 | |
| } |