1099 lines
33 KiB
PHP
1099 lines
33 KiB
PHP
<?php
|
|
/**
|
|
* Attachments for extensions
|
|
*
|
|
* @package Attachments
|
|
* @subpackage Attachments_Plugin_Framework
|
|
*
|
|
* @author Jonathan M. Cameron <jmcameron@jmcameron.net>
|
|
* @copyright Copyright (C) 2009-2018 Jonathan M. Cameron, All Rights Reserved
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL
|
|
* @link http://joomlacode.org/gf/project/attachments/frs/
|
|
*/
|
|
|
|
// No direct access
|
|
defined('_JEXEC') or die('Restricted access');
|
|
|
|
/** Load the attachments helper */
|
|
require_once JPATH_SITE . '/components/com_attachments/helper.php';
|
|
|
|
|
|
/**
|
|
* Plugins for Attachments
|
|
*
|
|
* AttachmentsPlugin is the base class for all the plugins to allow
|
|
* attaching files to various types of content entities
|
|
*
|
|
* The derived attachments plugin class must be in the main PHP file for that
|
|
* plugin. For instance for content articles or categories, the parent type
|
|
* is 'com_content'. The parent type is simply the name of the component
|
|
* involved (eg, 'com_content'). The derived attachments plugin class (such
|
|
* as 'AttachmentsPlugin_com_content') should be defined in the main file for
|
|
* the plugin (eg, attachments_for_conent.php).
|
|
*
|
|
* Derived attachments plugin classes must also include the following lines of
|
|
* code after the class definition to register the derived class with the
|
|
* Attachments plugin manager:
|
|
*
|
|
* $apm = getAttachmentsPluginManager();
|
|
* $apm->addParentType('com_content');
|
|
*
|
|
* where 'com_content' should be replaced by the name of the appropriate
|
|
* parent type (component).
|
|
*
|
|
* @package Attachments
|
|
* @since 3.0
|
|
*/
|
|
class AttachmentsPlugin extends JPlugin
|
|
{
|
|
/** Parent_type: com_content, com_quickfaq, etc
|
|
*/
|
|
protected $parent_type = null;
|
|
|
|
/** Name for the default parent_entity type
|
|
*
|
|
* Note that this name will be used for a directory for attachments entries
|
|
* and should not contain any spaces. It should correspond to the default
|
|
* entity. For instance, for com_content, it will be 'article';
|
|
*/
|
|
protected $default_entity = null;
|
|
|
|
/** known entities
|
|
*/
|
|
protected $entities = null;
|
|
|
|
/** An associative array of entity names
|
|
*
|
|
* For each type of attachments plugin, there will be a default
|
|
* entity types. For com_content, the default is 'article'. If
|
|
* the $default value for the function calls below is omitted,
|
|
* the entity is assumed to be 'article'. In some cases, the
|
|
* actual proper name of the entity will be available and will be
|
|
* passed in to the $default argument. It is important that the
|
|
* plugin code recognizes that the entity 'default' is an alias
|
|
* for 'article'. This array allows a simple associative array
|
|
* lookup to transform 'default' to 'article'.
|
|
*/
|
|
protected $entity_name = Array();
|
|
|
|
/** An associative array of entity tables
|
|
*/
|
|
protected $entity_table = Array();
|
|
|
|
/** An associative array of entity id fields
|
|
* (in same table as the title)
|
|
*/
|
|
protected $entity_id_field = Array();
|
|
|
|
/** An associative array of entity title fields
|
|
*/
|
|
protected $entity_title_field = Array();
|
|
|
|
/** An associative array of parent creator user ID fields
|
|
*/
|
|
protected $parent_creator_id_field = Array();
|
|
|
|
/** Flag indicating if the language file haas been loaded
|
|
*/
|
|
protected $language_loaded = false;
|
|
|
|
/** Cache for parentExists check
|
|
*/
|
|
protected $parent_exists_cache = Array();
|
|
|
|
/** Cache for parent titles
|
|
*/
|
|
protected $title_cache = Array();
|
|
|
|
/** Cache for parameters for the com_attachments component
|
|
*/
|
|
private $com_attachments_params = null;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param object &$subject The object to observe
|
|
* @param array $config An optional associative array of configuration settings.
|
|
* Recognized key values include 'name', 'group', 'params', 'language'
|
|
* (this list is not meant to be comprehensive).
|
|
*/
|
|
public function __construct(&$subject, $config = array())
|
|
{
|
|
parent::__construct($subject, $config);
|
|
|
|
// Save the plugin type
|
|
$this->_type = 'attachments';
|
|
}
|
|
|
|
/**
|
|
* Get the attachments parameter object
|
|
*
|
|
* @return object com_attachments parameter object
|
|
*/
|
|
public function attachmentsParams()
|
|
{
|
|
if ($this->com_attachments_params == null)
|
|
{
|
|
jimport('joomla.application.component.helper');
|
|
$this->com_attachments_params = JComponentHelper::getParams('com_attachments');
|
|
}
|
|
|
|
return $this->com_attachments_params;
|
|
}
|
|
|
|
/**
|
|
* Return the parent entity / row ID
|
|
*
|
|
* This will only be called by the main attachments 'onPrepareContent'
|
|
* plugin if $attachment ($row) does not have an id
|
|
*
|
|
* @param object &$attachment the attachment
|
|
*
|
|
* @return id if found, false if this is not a valid parent
|
|
*/
|
|
public function getParentId(&$attachment)
|
|
{
|
|
return JRequest::getInt('id', false);
|
|
}
|
|
|
|
/**
|
|
* Return the component name for this parent object
|
|
*
|
|
* @return the component name for this parent object
|
|
*/
|
|
public function getParentType()
|
|
{
|
|
return $this->parent_type;
|
|
}
|
|
|
|
/**
|
|
* Return a string of the where clause for filtering the the backend list of attachments
|
|
*
|
|
* @param string $parent_state the state ('ALL', 'PUBLISHED', 'UNPUBLISHED', 'ARCHIVED', 'NONE')
|
|
* @param string $filter_entity the entity filter ('ALL', 'ARTICLE', 'CATEGORY', etc)
|
|
*
|
|
* @return an array of (join_clause, where_clause) items
|
|
*/
|
|
public function getParentPublishedFilter($parent_state, $filter_entity)
|
|
{
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Determine the parent entity
|
|
*
|
|
* From the view and the class of the parent (row of onPrepareContent plugin),
|
|
* determine what the entity type is for this entity.
|
|
*
|
|
* Derived classes MUST overrride this
|
|
*
|
|
* @param &object &$parent The object for the parent (row) that onPrepareContent gets
|
|
*
|
|
* @return the correct entity (eg, 'default', 'category', etc) or false if this entity should not be displayed.
|
|
*/
|
|
public function determineParentEntity(&$parent)
|
|
{
|
|
return 'default';
|
|
}
|
|
|
|
/**
|
|
* Return the name of the field with the content item text
|
|
*
|
|
* During the display of content items (eg, articles, categories), the
|
|
* onContentPrepare (etc) callbacks are used to insert attachments lists.
|
|
* The second argument of the onContentPrepare() function is an object
|
|
* (usually $row) for the content item (eg, article). This function will
|
|
* return the appropriate field for the text of the content item. In some
|
|
* cases it is 'text', in others, 'introtext'. Attachments plugins can
|
|
* override this function to provide the field name more intelligently.
|
|
*
|
|
* Note: returns null if the text field is unknown/not present.
|
|
*
|
|
* @param &object &$row the content object (eg, article) being displayed
|
|
* @param string $parent_entity the type of entity for this content item.
|
|
*
|
|
* @return string name of the text field of this content item object.
|
|
*/
|
|
protected function getTextFieldName(&$row, $parent_entity)
|
|
{
|
|
$text_field_name = null;
|
|
|
|
// Ignore items without the normal 'text' field
|
|
if (isset($row->text))
|
|
{
|
|
$text_field_name = 'text';
|
|
}
|
|
elseif (isset($row->fulltext))
|
|
{
|
|
$text_field_name = 'fulltext';
|
|
}
|
|
elseif (isset($row->introtext))
|
|
{
|
|
$text_field_name = 'introtext';
|
|
}
|
|
|
|
return $text_field_name;
|
|
}
|
|
|
|
/**
|
|
* Return the array of entity IDs for all content items supported by this parent object
|
|
*
|
|
* @return the array of entities supported by this parent object
|
|
*/
|
|
public function getEntities()
|
|
{
|
|
return $this->entities;
|
|
}
|
|
|
|
/**
|
|
* Get the default entity ID
|
|
*
|
|
* @return string the default entity ID
|
|
*/
|
|
public function getDefaultEntity()
|
|
{
|
|
return $this->default_entity;
|
|
}
|
|
|
|
/**
|
|
* Get the canonical extension entity Id (eg, 'article' instead of 'default')
|
|
*
|
|
* This is the canonical Id of content element/item to which attachments will be added.
|
|
*
|
|
* that each content type ($option) may support several different entities
|
|
* (for attachments) and some entities may have more than one name.
|
|
*
|
|
* Note, for com_content, the default is 'article'
|
|
*
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return the canonical extension entity
|
|
*/
|
|
public function getCanonicalEntityId($parent_entity)
|
|
{
|
|
// It it is a known entity, just return it
|
|
if (is_array($this->entities) && in_array($parent_entity, $this->entities))
|
|
{
|
|
return $parent_entity;
|
|
}
|
|
|
|
// Check aliases
|
|
if (is_array($this->entities) && array_key_exists($parent_entity, $this->entity_name))
|
|
{
|
|
return $this->entity_name[$parent_entity];
|
|
}
|
|
else
|
|
{
|
|
$lang = JFactory::getLanguage();
|
|
$lang->load('plg_attachments_attachments_plugin_framework', dirname(__FILE__));
|
|
$errmsg = JText::sprintf('ATTACH_ERROR_INVALID_ENTITY_S_FOR_PARENT_S', $parent_entity, $this->parent_type) . ' (ERR 300)';
|
|
JError::raiseError(500, $errmsg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the path for the uploaded file (on the server file system)
|
|
*
|
|
* Note that this does not include the base directory for attachments.
|
|
*
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
* @param int $parent_id the ID for the parent object
|
|
* @param int $attachment_id the ID for the attachment
|
|
*
|
|
* @return string the directory name for this entity (with trailing '/'!)
|
|
*/
|
|
public function getAttachmentPath($parent_entity, $parent_id, $attachment_id)
|
|
{
|
|
$parent_entity = $this->getCanonicalEntityId($parent_entity);
|
|
|
|
$path = sprintf("%s/%d/", $parent_entity, $parent_id);
|
|
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Get the name or title for the specified object
|
|
*
|
|
* @param int $parent_id the ID for this parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return the name or title for the specified object
|
|
*/
|
|
public function getTitle($parent_id, $parent_entity = 'default')
|
|
{
|
|
// Short-circuit if there is no parent ID
|
|
if (!is_numeric($parent_id))
|
|
{
|
|
return '';
|
|
}
|
|
|
|
$parent_entity = $this->getCanonicalEntityId($parent_entity);
|
|
|
|
// Check the cache first
|
|
$cache_key = $parent_entity . (int) $parent_id;
|
|
if (array_key_exists($cache_key, $this->title_cache))
|
|
{
|
|
return $this->title_cache[$cache_key];
|
|
}
|
|
|
|
$entity_table = $this->entity_table[$parent_entity];
|
|
$entity_title_field = $this->entity_title_field[$parent_entity];
|
|
$entity_id_field = $this->entity_id_field[$parent_entity];
|
|
|
|
// Make sure the parent exists
|
|
if (!$this->parentExists($parent_id, $parent_entity))
|
|
{
|
|
/* Do not error out; this is most likely to occur in the backend
|
|
* when an article with attachments has been deleted without
|
|
* deleting the attachments. But we still need list it!
|
|
*/
|
|
return '';
|
|
}
|
|
|
|
// Look up the title
|
|
$db = JFactory::getDBO();
|
|
$query = $db->getQuery(true);
|
|
$query->select($entity_title_field)->from("#__$entity_table");
|
|
$query->where("$entity_id_field=" . (int) $parent_id);
|
|
$db->setQuery($query);
|
|
$title = $db->loadResult();
|
|
if ($db->getErrorNum())
|
|
{
|
|
$parent_entity_name = JText::_('ATTACH_' . $parent_entity);
|
|
$errmsg = JText::sprintf('ATTACH_ERROR_GETTING_PARENT_S_TITLE_FOR_ID_N',
|
|
$parent_entity_name, $parent_id) . ' (ERR 301)';
|
|
JError::raiseError(500, $errmsg);
|
|
}
|
|
|
|
$this->title_cache[$cache_key] = $title;
|
|
|
|
return $this->title_cache[$cache_key];
|
|
}
|
|
|
|
/**
|
|
* Return an array of entity items (with id,title pairs for each item)
|
|
*
|
|
* @param string $parent_entity the type of entity to search for
|
|
* @param string $filter filter the results for matches for this filter string
|
|
*
|
|
* @return the array of entity id,title pairs
|
|
*/
|
|
public function getEntityItems($parent_entity = 'default', $filter = '')
|
|
{
|
|
$parent_entity = $this->getCanonicalEntityId($parent_entity);
|
|
|
|
$entity_table = $this->entity_table[$parent_entity];
|
|
$entity_title_field = $this->entity_title_field[$parent_entity];
|
|
$entity_id_field = $this->entity_id_field[$parent_entity];
|
|
|
|
// Get the ordering information
|
|
$app = JFactory::getApplication();
|
|
$order = $app->getUserStateFromRequest('com_attachments.selectEntity.filter_order',
|
|
'filter_order', '', 'cmd');
|
|
$order_Dir = $app->getUserStateFromRequest('com_attachments.selectEntity.filter_order_Dir',
|
|
'filter_order_Dir', '', 'word');
|
|
|
|
// Get all the items
|
|
$db = JFactory::getDBO();
|
|
$query = $db->getQuery(true);
|
|
$query->select("DISTINCT $entity_id_field,$entity_title_field");
|
|
$query->from("#__$entity_table");
|
|
if ($filter)
|
|
{
|
|
$filter = $db->quote('%' . $db->escape($filter, true) . '%', false);
|
|
$query->where($entity_title_field . ' LIKE ' . $filter);
|
|
}
|
|
|
|
if ($order)
|
|
{
|
|
if ($order == 'title')
|
|
{
|
|
$query->order("$entity_title_field " . $order_Dir);
|
|
}
|
|
elseif ($order == 'id')
|
|
{
|
|
$query->order("$entity_id_field " . $order_Dir);
|
|
}
|
|
else
|
|
{
|
|
// Ignore unrecognized columns
|
|
}
|
|
}
|
|
|
|
// Do the query
|
|
$db->setQuery($query);
|
|
if ($db->getErrorNum())
|
|
{
|
|
$parent_entity_name = JText::_('ATTACH_' . $parent_entity);
|
|
$errmsg = JText::sprintf('ATTACH_ERROR_GETTING_LIST_OF_ENTITY_S_ITEMS', $parent_entity_name) . ' (ERR 302)';
|
|
JError::raiseError(500, $errmsg);
|
|
}
|
|
else
|
|
{
|
|
$items = $db->loadObjectList();
|
|
}
|
|
|
|
if ($items == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Make sure the the ids are called 'id' in the list
|
|
if ($entity_id_field != 'id')
|
|
{
|
|
foreach ($items as $item)
|
|
{
|
|
$item->id = $item->$entity_id_field;
|
|
}
|
|
}
|
|
|
|
// Make sure the the titles are called 'title' in the list
|
|
if ($entity_title_field != 'title')
|
|
{
|
|
foreach ($items as $item)
|
|
{
|
|
$item->title = $item->$entity_title_field;
|
|
}
|
|
}
|
|
|
|
return $items;
|
|
}
|
|
|
|
/**
|
|
* Return the URL that can be called to select a specific content item.
|
|
*
|
|
* @param string $parent_entity the type of entity to select from
|
|
*
|
|
* @return the URL that can be called to select a specific content item
|
|
*/
|
|
public function getSelectEntityURL($parent_entity = 'default')
|
|
{
|
|
// Add on the parent type and entity
|
|
$entity = "&parent_type=" . $this->parent_type;
|
|
|
|
if ($parent_entity != 'default')
|
|
{
|
|
$entity .= '.' . $parent_entity;
|
|
}
|
|
|
|
return "index.php?option=com_attachments&task=selectEntity" . $entity . "&tmpl=component";
|
|
}
|
|
|
|
/**
|
|
* Return the ID of the creator/owner of the parent entity
|
|
*
|
|
* @param int $parent_id the ID for the parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return creators id if found, 0 otherwise
|
|
*/
|
|
public function getParentCreatorId($parent_id, $parent_entity = 'default')
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
/**
|
|
* Get a URL to view the entity
|
|
*
|
|
* @param int $parent_id the ID for this parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return a URL to view the entity (non-SEF form)
|
|
*/
|
|
public function getEntityViewURL($parent_id, $parent_entity = 'default')
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get a URL to add an attachment to a specific entity
|
|
*
|
|
* @param int $parent_id the ID for the parent entity object (null if the parent does not exist)
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
* @param string $from where the call should return to
|
|
*
|
|
* @return the url to add a new attachments to the specified entity
|
|
*/
|
|
public function getEntityAddUrl($parent_id, $parent_entity = 'default', $from = 'closeme')
|
|
{
|
|
$app = JFactory::getApplication();
|
|
|
|
if ($app->isAdmin())
|
|
{
|
|
$task = 'add';
|
|
}
|
|
else
|
|
{
|
|
$task = 'upload';
|
|
}
|
|
|
|
$url = "index.php?option=com_attachments&task=$task";
|
|
if ($parent_id == null)
|
|
{
|
|
$url .= "&parent_id=$parent_id,new";
|
|
}
|
|
else
|
|
{
|
|
$url .= "&parent_id=$parent_id";
|
|
}
|
|
|
|
$url .= "&parent_type=" . $this->parent_type . "&from=$from";
|
|
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Check to see if a custom title applies to this parent
|
|
*
|
|
* Note: this public function assumes that the parent_id's match
|
|
*
|
|
* @param string $parent_entity the parent entity for the parent of the list
|
|
* @param string $rtitle_parent_entity the entity of the candidate attachment list title (from params)
|
|
*
|
|
* @return true if the custom title should be used
|
|
*/
|
|
public function checkAttachmentsListTitle($parent_entity, $rtitle_parent_entity)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get the title for the attachments list for this parent
|
|
*
|
|
* @param string $title the untranslated title token (either 'ATTACH_ATTACHMENTS_TITLE' or 'ATTACH_EXISTING_ATTACHMENTS')
|
|
* @param int $parent_id the ID for the parent entity object (null if the parent does not exist)
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return the translated title string
|
|
*/
|
|
public function attachmentsListTitle($title, $parent_id, $parent_entity = 'default')
|
|
{
|
|
$aparams = $this->attachmentsParams();
|
|
$rtitle_str = $aparams->get('attachments_titles', '');
|
|
if (($title != 'ATTACH_EXISTING_ATTACHMENTS') && ($rtitle_str != ''))
|
|
{
|
|
$rtitle_list = preg_split("[\n|\r]", $rtitle_str);
|
|
|
|
foreach ($rtitle_list as $rtitle)
|
|
{
|
|
if (preg_match('|^([0-9]+)\s*([^$]+)$|', $rtitle, $match))
|
|
{
|
|
// Process: 3 new title
|
|
// NOTE: This form only applies to articles and will be ignored for anything else
|
|
if ((int) $parent_id != (int) $match[1])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (($this->parent_type == 'com_content') && (($parent_entity == 'default') || ($parent_entity == 'article')))
|
|
{
|
|
$title = $match[2];
|
|
}
|
|
}
|
|
elseif (preg_match('|^([a-zA-Z0-9_/-]+):([0-9]+)\s*([^$]+)$|', $rtitle, $match))
|
|
{
|
|
// Process: entity:3 new title
|
|
if ((int) $parent_id != (int) $match[2])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ($this->checkAttachmentsListTitle($parent_entity, $match[1]))
|
|
{
|
|
$title = $match[3];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// With no entity/numeric prefix, the title applies to all attachments lists
|
|
$rtitle = trim($rtitle);
|
|
if ($rtitle != '')
|
|
{
|
|
$title = $rtitle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return JText::_($title);
|
|
}
|
|
|
|
/**
|
|
* Does the parent exist?
|
|
*
|
|
* @param int $parent_id the ID for this parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return true if the parent exists
|
|
*/
|
|
public function parentExists($parent_id, $parent_entity = 'default')
|
|
{
|
|
$parent_entity = $this->getCanonicalEntityId($parent_entity);
|
|
|
|
// Check the cache first
|
|
$cache_key = $parent_entity . (int) $parent_id;
|
|
if (array_key_exists($cache_key, $this->parent_exists_cache))
|
|
{
|
|
return $this->parent_exists_cache[$cache_key];
|
|
}
|
|
|
|
// First time, so look up the parent
|
|
$entity_table = $this->entity_table[$parent_entity];
|
|
$entity_id_field = $this->entity_id_field[$parent_entity];
|
|
$db = JFactory::getDBO();
|
|
$query = $db->getQuery(true);
|
|
$query->select($entity_id_field)->from("#__$entity_table");
|
|
$query->where("$entity_id_field=" . (int) $parent_id);
|
|
$db->setQuery($query, 0, 1);
|
|
$result = $db->loadResult();
|
|
if ($result === null)
|
|
{
|
|
$this->parent_exists_cache[$cache_key] = false;
|
|
}
|
|
else
|
|
{
|
|
$this->parent_exists_cache[$cache_key] = (int) $parent_id == (int) $result;
|
|
}
|
|
|
|
return $this->parent_exists_cache[$cache_key];
|
|
}
|
|
|
|
/**
|
|
* Is the parent new (based on the parent_id)
|
|
*
|
|
* @param object &$attachment the attachment
|
|
*
|
|
* @return true if the parent is new (being created)
|
|
*/
|
|
public function newParent(&$attachment)
|
|
{
|
|
// Assume parent_id == 0 means the parent is new
|
|
// (NOTE: This may not be true for some components)
|
|
return $attachment->parent_id == 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Check to see if the parent is published
|
|
*
|
|
* @param int $parent_id the ID for this parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return true if the parent is published
|
|
*/
|
|
public function isParentPublished($parent_id, $parent_entity = 'default')
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check to see if the parent is archived
|
|
*
|
|
* @param int $parent_id the ID for this parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return true if the parent is archived
|
|
*/
|
|
public function isParentArchived($parent_id, $parent_entity = 'default')
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* May the parent be viewed by the user?
|
|
*
|
|
* This public function should be called by derived class functions.
|
|
*
|
|
* Note that this base class function only determines necessary
|
|
* conditions. If this function returns FALSE, then viewing is definitely
|
|
* not permitted. If this function returns TRUE, then the derived classes
|
|
* also need to check whether viewing the specific content item (eg,
|
|
* article) is permitted.
|
|
*
|
|
* @param int $parent_id the ID for this parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
* @param object $user_id the user_id to check (optional, primarily for testing)
|
|
*
|
|
* @return true if the parent may be viewed by the user
|
|
*/
|
|
public function userMayViewParent($parent_id, $parent_entity = 'default', $user_id = null)
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
/** Return true if the attachments should be hidden for this parent
|
|
*
|
|
* @param &object &$parent the object for the parent that onPrepareContent gives
|
|
* @param int $parent_id the ID of the parent the attachment is attached to
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* Note: this generic version only implements the 'frontpage' option. All
|
|
* other options should be handled by the derived classes for other
|
|
* content types.
|
|
*
|
|
* @return true if the attachments should be hidden for this parent
|
|
*/
|
|
public function attachmentsHiddenForParent(&$parent, $parent_id, $parent_entity)
|
|
{
|
|
$layout = JRequest::getCmd('layout');
|
|
$aparams = $this->attachmentsParams();
|
|
|
|
// Check to see whether the attachments should be hidden on the front page
|
|
$hide_on_frontpage = $aparams->get('hide_on_frontpage', false);
|
|
if ($hide_on_frontpage && (JRequest::getVar('view') == 'featured'))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Hide on blog pages?
|
|
$hide_on_blogs = $aparams->get('hide_on_blogs', false);
|
|
if ($hide_on_blogs && ($layout == 'blog'))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return true if the user may add an attachment to this parent
|
|
*
|
|
* (Note that all of the arguments are assumed to be valid; no sanity checking is done.
|
|
* It is up to the caller to validate these objects before calling this function.)
|
|
*
|
|
* @param int $parent_id the ID of the parent the attachment is attached to
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
* @param bool $new_parent if true, the parent is being created and does not exist yet
|
|
* @param object $user_id the user_id to check (optional, primarily for testing)
|
|
*
|
|
* @return true if this user add attachments to this parent
|
|
*/
|
|
public function userMayAddAttachment($parent_id, $parent_entity, $new_parent = false, $user_id = null)
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
/**
|
|
* Return true if this user may edit (modify/delete/update) this attachment for this parent
|
|
*
|
|
* (Note that all of the arguments are assumed to be valid; no sanity checking is done.
|
|
* It is up to the caller to validate the arguments before calling this function.)
|
|
*
|
|
* @param &record &$attachment database record for the attachment
|
|
* @param object $user_id the user_id to check (optional, primarily for testing)
|
|
*
|
|
* @return true if this user may edit this attachment
|
|
*/
|
|
public function userMayEditAttachment(&$attachment, $user_id = null)
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
/**
|
|
* Return true if this user may delete this attachment for this parent
|
|
*
|
|
* (Note that all of the arguments are assumed to be valid; no sanity checking is done.
|
|
* It is up to the caller to validate the arguments before calling this function.)
|
|
*
|
|
* @param &record &$attachment database record for the attachment
|
|
* @param object $user_id the user_id to check (optional, primarily for testing)
|
|
*
|
|
* @return true if this user may delete this attachment
|
|
*/
|
|
public function userMayDeleteAttachment(&$attachment, $user_id = null)
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
/**
|
|
* Return true if this user may change the state of this attachment
|
|
*
|
|
* (Note that all of the arguments are assumed to be valid; no sanity checking is done.
|
|
* It is up to the caller to validate the arguments before calling this function.)
|
|
*
|
|
* @param int $parent_id the ID for the parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
* @param int $attachment_creator_id the ID of the creator of the attachment
|
|
* @param object $user_id the user_id to check (optional, primarily for testing)
|
|
*
|
|
* @return true if this user may change the state of this attachment
|
|
*/
|
|
public function userMayChangeAttachmentState($parent_id, $parent_entity, $attachment_creator_id, $user_id = null)
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
/** Check to see if the user may access (see/download) the attachments
|
|
*
|
|
* @param &record &$attachment database record for the attachment
|
|
* @param object $user_id the user_id to check (optional, primarily for testing)
|
|
*
|
|
* @return true if access is okay (false if not)
|
|
*/
|
|
public function userMayAccessAttachment(&$attachment, $user_id = null)
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
/** Insert the attachments list into the content text (for front end)
|
|
*
|
|
* @param object &$content the text of the content item (eg, article text)
|
|
* @param int $parent_id the ID for the parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return string the modified content text (false for failure)
|
|
*/
|
|
public function insertAttachmentsList(&$content, $parent_id, $parent_entity)
|
|
{
|
|
$aparams = $this->attachmentsParams();
|
|
|
|
// Get the desired placement
|
|
$attachments_placement = $aparams->get('attachments_placement', 'end');
|
|
if ($attachments_placement == 'disabled_nofilter')
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Determine where we are
|
|
$from = JRequest::getCmd('view', 'closeme');
|
|
$Itemid = JRequest::getInt('Itemid', 1);
|
|
|
|
// See whether we can display the links to add attachments
|
|
$user_can_add = $this->userMayAddAttachment($parent_id, $parent_entity);
|
|
|
|
// Get the field name for the content item's text
|
|
$text_field_name = $this->getTextFieldName($content, $parent_entity);
|
|
if ($text_field_name === null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get the attachments tag, if present
|
|
$attachments_tag = '';
|
|
$attachments_tag_args = '';
|
|
$match = false;
|
|
if (JString::strpos($content->$text_field_name, '{attachments'))
|
|
{
|
|
if (preg_match('@(<span class="hide_attachments_token">)?{attachments([ ]*:*[^}]+)?}(</span>)?@', $content->$text_field_name, $match))
|
|
{
|
|
$attachments_tag = true;
|
|
}
|
|
|
|
if (isset($match[1]) && $match[1])
|
|
{
|
|
$attachments_tag_args_raw = $match[1];
|
|
$attachments_tag_args = ltrim($attachments_tag_args_raw, ' :');
|
|
}
|
|
|
|
if ($attachments_tag)
|
|
{
|
|
$attachments_tag = $match[0];
|
|
}
|
|
}
|
|
|
|
// Check the security status
|
|
$attach_dir = JPATH_SITE . '/' . AttachmentsDefines::$ATTACHMENTS_SUBDIR;
|
|
$secure = $aparams->get('secure', false);
|
|
$hta_filename = $attach_dir . '/ . htaccess';
|
|
if (($secure && !file_exists($hta_filename)) || (!$secure && file_exists($hta_filename)))
|
|
{
|
|
AttachmentsHelper::setup_upload_directory($attach_dir, $secure);
|
|
}
|
|
|
|
// Construct the attachment list (if appropriate)
|
|
$html = '';
|
|
$attachments_list = false;
|
|
$add_attachement_btn = false;
|
|
|
|
// Get the html for the attachments list
|
|
require_once JPATH_SITE . '/components/com_attachments/controllers/attachments.php';
|
|
$controller = new AttachmentsControllerAttachments;
|
|
$attachments_list = $controller->displayString($parent_id, $this->parent_type, $parent_entity, null, true, true, false, $from);
|
|
|
|
// If the attachments list is empty, insert an empty div for it
|
|
if ($attachments_list == '')
|
|
{
|
|
$class_name = $aparams->get('attachments_table_style', 'attachmentsList');
|
|
$div_id = 'attachmentsList' . '_' . $this->parent_type . '_' . $parent_entity . '_' . (string) $parent_id;
|
|
$attachments_list = "\n<div class=\"$class_name\" id=\"$div_id\"></div>\n";
|
|
}
|
|
|
|
$html .= $attachments_list;
|
|
|
|
if ($html || $user_can_add)
|
|
{
|
|
// Add the style sheet
|
|
JHtml::stylesheet('com_attachments/attachments_list.css', Array(), true);
|
|
|
|
// Handle RTL styling (if necessary)
|
|
$lang = JFactory::getLanguage();
|
|
if ($lang->isRTL())
|
|
{
|
|
JHtml::stylesheet('com_attachments/attachments_list_rtl.css', Array(), true);
|
|
}
|
|
}
|
|
|
|
// Construct the add-attachments button, if appropriate
|
|
$hide_add_attachments_link = $aparams->get('hide_add_attachments_link', 0);
|
|
if ($user_can_add && !$hide_add_attachments_link)
|
|
{
|
|
$add_attachments_btn = AttachmentsHelper::attachmentButtonsHTML($this->parent_type, $parent_id, $parent_entity, $Itemid, $from);
|
|
$html .= $add_attachments_btn;
|
|
}
|
|
|
|
// Wrap both list and the Add Attachments button in another div
|
|
if ($html)
|
|
{
|
|
$html = "<div class=\"attachmentsContainer\">\n" . $html . "\n</div>";
|
|
}
|
|
|
|
// Finally, add the attachments
|
|
|
|
// NOTE: Hope str_replace() below is UTF8 safe (since the token being replaced is UTF8)...
|
|
|
|
switch ($attachments_placement)
|
|
{
|
|
case 'beginning':
|
|
// Put the attachments list at the beginning
|
|
if ($attachments_list || $user_can_add)
|
|
{
|
|
if ($attachments_tag)
|
|
{
|
|
$content->$text_field_name = $html . $content->$text_field_name;
|
|
}
|
|
else
|
|
{
|
|
$content->$text_field_name = $html . str_replace($attachments_tag, '', $content->$text_field_name);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'custom':
|
|
// Insert the attachments at the desired location
|
|
if ($attachments_list || $user_can_add)
|
|
{
|
|
if ($attachments_tag)
|
|
{
|
|
$content->$text_field_name = str_replace($attachments_tag, $html, $content->$text_field_name);
|
|
}
|
|
else
|
|
{
|
|
// If there is no tag, insert the attachments at the end
|
|
$content->$text_field_name .= $html;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'disabled_filter':
|
|
// Disable and strip out any attachments tags
|
|
if ($attachments_tag)
|
|
{
|
|
$content->$text_field_name = str_replace($attachments_tag, '', $content->$text_field_name);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// Add the attachments to the end
|
|
if ($attachments_list || $user_can_add)
|
|
{
|
|
if ($attachments_tag)
|
|
{
|
|
$content->$text_field_name = str_replace($attachments_tag, '', $content->$text_field_name) . $html;
|
|
}
|
|
else
|
|
{
|
|
$content->$text_field_name .= $html;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
|
|
/** Get the parent_id in the component content item editor
|
|
* (the article or category editor)
|
|
*
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
*
|
|
* @return the parent ID, null if the content item is being created, and false if there is no match
|
|
*
|
|
* @since Attachments 3.2
|
|
*/
|
|
public function getParentIdInEditor($parent_entity, $view, $layout)
|
|
{
|
|
// This should work in the backend for most well-implemented content types--
|
|
// but not for all frontends, especially not com_content/articles
|
|
$id = null;
|
|
if ($view == $parent_entity) {
|
|
$id = JRequest::getInt('id', $default=null);
|
|
}
|
|
else {
|
|
$id = false;
|
|
}
|
|
|
|
// If we got one, convert it to an int
|
|
if (is_numeric($id)) {
|
|
$id = (int)$id;
|
|
}
|
|
|
|
return $id;
|
|
}
|
|
|
|
|
|
/** See if the attachments list should be displayed in its content description editor
|
|
*
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
* @param string $view the view
|
|
* @param string $layout the layout on the view
|
|
*
|
|
* @return true if the attachments list should be added to the editor
|
|
*/
|
|
public function showAttachmentsInEditor($parent_entity, $view, $layout)
|
|
{
|
|
JError::raiseError(501, JText::_('ATTACH_NOT_IMPLEMENTED'));
|
|
}
|
|
|
|
|
|
/** Insert the attachments list into the entity editor page
|
|
*
|
|
* @param int $parent_id the ID for the parent object
|
|
* @param string $parent_entity the type of entity for this parent type
|
|
* @param string $attachments the attachments list as a string
|
|
* @param string $body the editor page text
|
|
*
|
|
* @return string the modified editor page text (false for failure)
|
|
*/
|
|
public function insertAttachmentsListInEditor($parent_id, $parent_entity, $attachments, $body)
|
|
{
|
|
// Figure out where to insert the attachments list
|
|
$reptag = '<div id="editor-xtd-buttons"';
|
|
if (version_compare(JVERSION, '3.5', 'ge')) {
|
|
if (JFactory::getEditor()->get('_name') == 'tinymce') {
|
|
# Hack because TinyMCE changed the structure
|
|
$reptag = '<div class="toggle-editor btn-toolbar pull-right clearfix"';
|
|
}
|
|
}
|
|
|
|
// Insert the attachments above the editor buttons
|
|
// NOTE: Assume that anyone editing the entity can see its attachments
|
|
$body = str_replace($reptag, $attachments . $reptag, $body);
|
|
return $body;
|
|
}
|
|
|
|
|
|
/** Known from keywords
|
|
*
|
|
* Attachment pop-dialogs will be closed using javascript if they are called from pages of these 'from' types
|
|
*
|
|
* @retrun array An array of known tokens (strings)
|
|
*/
|
|
public function knownFroms()
|
|
{
|
|
// Most components should recognize these
|
|
return Array('editor', 'closeme');
|
|
}
|
|
|
|
}
|