Server : Apache System : Linux indy02.toastserver.com 3.10.0-962.3.2.lve1.5.85.el7.x86_64 #1 SMP Thu Apr 18 15:18:36 UTC 2024 x86_64 User : palandch ( 1163) PHP Version : 7.1.33 Disable Function : NONE Directory : /home/palandch/www/core/model/modx/sources/ |
<?php /** * @package modx * @subpackage sources */ /** * The interface used for defining common methods for Media Source drivers * @package modx */ interface modMediaSourceInterface /** * Initialize the source, preparing it for usage. * * @return boolean */{ public function initialize(); /** * Return an array of containers at this current level in the container structure. Used for the tree * navigation on the files tree. * * @abstract * @param string $path * @return array */ public function getContainerList($path); /** * Return a detailed list of objects in a specific path. Used for thumbnails in the Browser. * * @param string $path * @return array */ public function getObjectsInContainer($path); /** * Create a container at the passed location with the passed name * * @abstract * @param string $name * @param string $parentContainer * @return boolean */ public function createContainer($name,$parentContainer); /** * Remove the specified container * * @abstract * @param string $path * @return boolean */ public function removeContainer($path); /** * Rename a container * * @abstract * @param string $oldPath * @param string $newName * @return boolean */ public function renameContainer($oldPath,$newName); /** * Upload objects to a specific container * * @abstract * @param string $container * @param array $objects * @return boolean */ public function uploadObjectsToContainer($container,array $objects = array()); /** * Get the contents of an object * * @abstract * @param string $objectPath * @return boolean */ public function getObjectContents($objectPath); /** * Update the contents of a specific object * * @abstract * @param string $objectPath * @param string $content * @return boolean */ public function updateObject($objectPath,$content); /** * Create an object from a path * * @param string $objectPath * @param string $name * @param string $content * @return boolean|string */ public function createObject($objectPath,$name,$content); /** * Remove an object * * @abstract * @param string $objectPath * @return boolean */ public function removeObject($objectPath); /** * Rename a file/object * * @abstract * @param string $oldPath * @param string $newName * @return bool */ public function renameObject($oldPath,$newName); /** * Get the openTo path for this source, used with TV input types and Static Elements/Resources * * @param string $value * @param array $parameters * @return string */ public function getOpenTo($value,array $parameters = array()); /** * Get the base path for this source. Only applicable to sources that are streams, used for determining * the base path with Static objects. * * @param string $object An optional file to find the base path with * @return string */ public function getBasePath($object = ''); /** * Get the base URL for this source. Only applicable to sources that are streams; used for determining the base * URL with Static objects and downloading objects. * * @abstract * @param string $object * @return void */ public function getBaseUrl($object = ''); /** * Get the URL for an object in this source. Only applicable to sources that are streams; used for determining * the base URL with Static objects and downloading objects. * * @abstract * @param string $object * @return void */ public function getObjectUrl($object = ''); /** * Move a file or folder to a specific location * * @param string $from The location to move from * @param string $to The location to move to * @param string $point The type of move; append, above, below * @return boolean */ public function moveObject($from,$to,$point = 'append'); /** * Get the name of this source type, ie, "File System" * @return string */ public function getTypeName(); /** * Get a short description of this source type * @return string */ public function getTypeDescription(); /** * Get the default properties for this source. Override this in your custom source driver to provide custom * properties for your source type. * @return array */ public function getDefaultProperties(); } /** * An abstract base class used for determining functionality of different media source drivers. Extend this class in * and implement modMediaSourceInterface in your driver implementations to provide custom functionality for different * types of media sources. * * Of course, in your getContainerList method, you can define the context menu items for the tree, so not all of these * methods might need to be implemented, depending on your situation. You can also provide custom actions for your * source type, depending on the behavior you might need. * * @package modx * @subpackage sources */ class modMediaSource extends modAccessibleSimpleObject implements modMediaSourceInterface { /** @var modX|xPDO $xpdo */ public $xpdo; /** @var modContext $ctx */ public $ctx; /** @var array $properties */ public $properties = array(); /** @var array $permissions */ public $permissions = array(); /** @var array $errors */ public $errors = array(); /** * Get the default MODX filesystem source * @static * @param xPDO|modX $xpdo A reference to an xPDO instance * @param int $defaultSourceId * @param boolean $fallbackToDefault * @return modMediaSource|null */ public static function getDefaultSource(xPDO &$xpdo,$defaultSourceId = null,$fallbackToDefault = true) { if (empty($defaultSourceId)) { $defaultSourceId = $xpdo->getOption('default_media_source',null,1); } /** @var modMediaSource $defaultSource */ $defaultSource = $xpdo->getObject('sources.modMediaSource',array( 'id' => $defaultSourceId, )); if (empty($defaultSource) && $fallbackToDefault) { $c = $xpdo->newQuery('sources.modMediaSource'); $c->sortby('id','ASC'); $defaultSource = $xpdo->getObject('sources.modMediaSource',$c); } return $defaultSource; } /** * Get the current working context for the processor * @return bool|modContext */ public function getWorkingContext() { $wctx = isset($this->properties['wctx']) && !empty($this->properties['wctx']) ? $this->properties['wctx'] : ''; if (!empty($wctx)) { $workingContext = $this->xpdo->getContext($wctx); if (!$workingContext) { return false; } } else { $workingContext =& $this->xpdo->context; } $this->ctx =& $workingContext; return $this->ctx; } /** * Initialize the source * @return boolean */ public function initialize() { $this->setProperties($this->getProperties(true)); $this->getPermissions(); return true; } /** * Setup the request properties for the source, determining any request-specific actions * @param array $scriptProperties * @return array */ public function setRequestProperties(array $scriptProperties = array()) { if (empty($this->properties)) $this->properties = array(); $this->properties = array_merge($this->getPropertyList(),$this->properties,$scriptProperties); return $this->properties; } /** * Get a list of permissions for browsing and utilizing the source. May be overridden to provide a custom * list of permissions. * @return array */ public function getPermissions() { $this->permissions = array( 'directory_chmod' => $this->xpdo->hasPermission('directory_chmod'), 'directory_create' => $this->xpdo->hasPermission('directory_create'), 'directory_list' => $this->xpdo->hasPermission('directory_list'), 'directory_remove' => $this->xpdo->hasPermission('directory_remove'), 'directory_update' => $this->xpdo->hasPermission('directory_update'), 'file_list' => $this->xpdo->hasPermission('file_list'), 'file_remove' => $this->xpdo->hasPermission('file_remove'), 'file_update' => $this->xpdo->hasPermission('file_update'), 'file_upload' => $this->xpdo->hasPermission('file_upload'), 'file_view' => $this->xpdo->hasPermission('file_view'), 'file_create' => $this->xpdo->hasPermission('file_create'), ); return $this->permissions; } /** * See if the source is allowing a certain permission. * * @param string $key * @return bool */ public function hasPermission($key) { return !empty($this->permissions[$key]); } /** * Add an error for an action occurring in the source * * @param string $field The field corresponding to the error * @param string $message The message to add * @return string The added error */ public function addError($field,$message) { $this->errors[$field] = $message; return $message; } /** * Get all errors that have occurred for this source * @return array */ public function getErrors() { return $this->errors; } /** * See if the source has any errors * @return bool */ public function hasErrors() { return !empty($this->errors); } public function getContainerList($path) { return array(); } public function getObjectsInContainer($path) { return array(); } public function createContainer($name,$parentContainer) { return true; } public function removeContainer($path) { return true; } public function renameContainer($oldPath,$newName) { return true; } public function updateContainer() { return true; } public function uploadObjectsToContainer($container,array $objects = array()) { return true; } public function getObjectContents($objectPath) { return true; } public function updateObject($objectPath,$content) { return true; } public function createObject($objectPath,$name,$content) { return true; } public function removeObject($objectPath) { return true; } public function renameObject($oldPath,$newName) { return true; } public function getBasePath($object = '') { return ''; } public function getBaseUrl($object = '') { return ''; } public function getObjectUrl($object = '') { return ''; } public function moveObject($from,$to,$point = 'append') { return true; } public function getDefaultProperties() { return array(); } /** * Get the openTo directory for this source, used with TV input types * * @param string $value * @param array $parameters * @return string */ public function getOpenTo($value,array $parameters = array()) { return dirname($value).'/'; } /** * Get the name of this source type * @return string */ public function getTypeName() { $this->xpdo->lexicon->load('source'); return $this->xpdo->lexicon('source_type.file'); } /** * Get the description of this source type * @return string */ public function getTypeDescription() { $this->xpdo->lexicon->load('source'); return $this->xpdo->lexicon('source_type.file_desc'); } /** * Get the properties on this source * @param boolean $parsed * @return array */ public function getProperties($parsed = false) { $properties = $this->get('properties'); $defaultProperties = $this->getDefaultProperties(); if (!empty($properties) && is_array($properties)) { foreach ($properties as &$property) { $property['overridden'] = 0; if (array_key_exists($property['name'],$defaultProperties)) { if ($defaultProperties[$property['name']]['value'] != $property['value']) { $property['overridden'] = 1; } } else { $property['overridden'] = 2; } } $properties = array_merge($defaultProperties,$properties); } else { $properties = $defaultProperties; } /** @var array $results Allow manipulation of media source properties via event */ $results = $this->xpdo->invokeEvent('OnMediaSourceGetProperties',array( 'properties' => $this->xpdo->toJSON($properties), )); if (!empty($results)) { foreach ($results as $result) { $result = is_array($result) ? $result : $this->xpdo->fromJSON($result); $properties = array_merge($properties,$result); } } if ($parsed) { $properties = $this->parseProperties($properties); } return $this->prepareProperties($properties); } /** * Get all properties in key => value format * @return array */ public function getPropertyList() { $properties = $this->getProperties(true); $list = array(); foreach ($properties as $property) { $value = $property['value']; if (!empty($property['xtype']) && $property['xtype'] == 'combo-boolean') { $value = empty($property['value']) && $property['value'] != 'true' ? false : true; } $list[$property['name']] = $value; } $list = array_merge($list,$this->properties); return $list; } /** * Parse any tags in the properties * @param array $properties * @return array */ public function parseProperties(array $properties) { $properties = $this->getProperties(); $this->xpdo->getParser(); if ($this->xpdo->parser) { foreach ($properties as &$property) { $this->xpdo->parser->processElementTags('',$property['value'],true,true); } } return $properties; } /** * Translate any needed properties * @param array $properties * @return array */ public function prepareProperties(array $properties = array()) { foreach ($properties as &$property) { if (!empty($property['lexicon'])) { $this->xpdo->lexicon->load($property['lexicon']); } if (!empty($property['name'])) { $property['name_trans'] = $this->xpdo->lexicon($property['name']); } if (!empty($property['desc'])) { $property['desc_trans'] = $this->xpdo->lexicon($property['desc']); } if (!empty($property['options'])) { foreach ($property['options'] as &$option) { if (empty($option['text']) && !empty($option['name'])) { $option['text'] = $option['name']; unset($option['name']); } if (empty($option['value']) && !empty($option[0])) { $option['value'] = $option[0]; unset($option[0]); } $option['name'] = $this->xpdo->lexicon($option['text']); } } } return $properties; } /** * Set the properties for this Source * * @param array $properties * @param boolean $merge * @return bool */ public function setProperties($properties, $merge = false) { $default = $this->getDefaultProperties(); foreach ($properties as $k => $prop) { if (is_array($prop) && array_key_exists($prop['name'],$default)) { if ($prop['value'] == $default[$prop['name']]['value']) { unset($properties[$k]); } } else if (is_scalar($prop)) { /* properties is k=>v pair */ if ($prop == $default[$k]['value']) { unset($properties[$k]); } } } $set = false; $propertiesArray = array(); if (is_string($properties)) { $properties = $this->xpdo->parser->parsePropertyString($properties); } if (is_array($properties)) { foreach ($properties as $propKey => $property) { if (is_array($property) && isset($property[5])) { $key = $property[0]; $propertyArray = array( 'name' => $property[0], 'desc' => $property[1], 'type' => $property[2], 'options' => $property[3], 'value' => $property[4], 'lexicon' => !empty($property[5]) ? $property[5] : null, ); } elseif (is_array($property) && isset($property['value'])) { $key = $property['name']; $propertyArray = array( 'name' => $property['name'], 'desc' => isset($property['description']) ? $property['description'] : (isset($property['desc']) ? $property['desc'] : ''), 'type' => isset($property['xtype']) ? $property['xtype'] : (isset($property['type']) ? $property['type'] : 'textfield'), 'options' => isset($property['options']) ? $property['options'] : array(), 'value' => $property['value'], 'lexicon' => !empty($property['lexicon']) ? $property['lexicon'] : null, ); } else { $key = $propKey; $propertyArray = array( 'name' => $propKey, 'desc' => '', 'type' => 'textfield', 'options' => array(), 'value' => $property, 'lexicon' => null, ); } if (!empty($propertyArray['options'])) { foreach ($propertyArray['options'] as $optionKey => &$option) { if (empty($option['text']) && !empty($option['name'])) $option['text'] = $option['name']; unset($option['menu'],$option['name']); } } if ($propertyArray['type'] == 'combo-boolean' && is_numeric($propertyArray['value'])) { $propertyArray['value'] = (boolean)$propertyArray['value']; } $propertiesArray[$key] = $propertyArray; } if ($merge && !empty($propertiesArray)) { $existing = $this->get('properties'); if (is_array($existing) && !empty($existing)) { $propertiesArray = array_merge($existing, $propertiesArray); } } $set = $this->set('properties', $propertiesArray); } return $set; } /** * Prepare the source path for phpThumb * * @param string $src * @return string */ public function prepareSrcForThumb($src) { /* dont strip stuff for absolute URLs */ if (substr($src,0,4) != 'http') { if (strpos($src,'/') !== 0) { $properties = $this->getPropertyList(); $src = !empty($properties['basePath']) ? $properties['basePath'].$src : $src; if (!empty($properties['basePathRelative'])) { $src = $this->ctx->getOption('base_path',null,MODX_BASE_PATH).$src; } } /* strip out double slashes */ $src = str_replace(array('///','//'),'/',$src); /* check for file existence if local url */ if (strpos($src,'/') !== 0 && empty($src)) { if (file_exists('/'.$src)) { $src = '/'.$src; } else { return ''; } } } return $src; } /** * Prepares the output URL when the Source is being used in an Element. Can be overridden to provide prefixing/post- * fixing functionality. * * @param string $value * @return string */ public function prepareOutputUrl($value) { return $value; } /** * Find all policies for this object * * @param string $context * @return array */ public function findPolicy($context = '') { $policy = array(); $enabled = true; $context = 'mgr'; if ($context === $this->xpdo->context->get('key')) { $enabled = (boolean) $this->xpdo->getOption('access_media_source_enabled', null, true); } elseif ($this->xpdo->getContext($context)) { $enabled = (boolean) $this->xpdo->contexts[$context]->getOption('access_media_source_enabled', true); } if ($enabled) { if (empty($this->_policies) || !isset($this->_policies[$context])) { $accessTable = $this->xpdo->getTableName('sources.modAccessMediaSource'); $sourceTable = $this->xpdo->getTableName('sources.modMediaSource'); $policyTable = $this->xpdo->getTableName('modAccessPolicy'); $sql = "SELECT Acl.target, Acl.principal, Acl.authority, Acl.policy, Policy.data FROM {$accessTable} Acl " . "LEFT JOIN {$policyTable} Policy ON Policy.id = Acl.policy " . "JOIN {$sourceTable} Source ON Acl.principal_class = 'modUserGroup' " . "AND (Acl.context_key = :context OR Acl.context_key IS NULL OR Acl.context_key = '') " . "AND Source.id = Acl.target " . "WHERE Acl.target = :source " . "GROUP BY Acl.target, Acl.principal, Acl.authority, Acl.policy"; $bindings = array( ':source' => $this->get('id'), ':context' => $context, ); $query = new xPDOCriteria($this->xpdo, $sql, $bindings); if ($query->stmt && $query->stmt->execute()) { while ($row = $query->stmt->fetch(PDO::FETCH_ASSOC)) { $policy['sources.modAccessMediaSource'][$row['target']][] = array( 'principal' => $row['principal'], 'authority' => $row['authority'], 'policy' => $row['data'] ? $this->xpdo->fromJSON($row['data'], true) : array(), ); } } $this->_policies[$context] = $policy; } else { $policy = $this->_policies[$context]; } } return $policy; } /** * Allow overriding of checkPolicy to always allow media sources to be loaded * * @param string|array $criteria * @param array $targets * @return bool */ public function checkPolicy($criteria, $targets = null) { if ($criteria == 'load') { $success = true; } else { $success = parent::checkPolicy($criteria,$targets); } return $success; } /** * Override xPDOObject::save to clear the sources cache on save * * @param boolean $cacheFlag * @return boolean */ public function save($cacheFlag = null) { $saved = parent::save($cacheFlag); if ($saved) { $this->clearCache(); } return $saved; } /** * Clear the caches of all sources * @param array $options * @return void */ public function clearCache(array $options = array()) { /** @var modCacheManager $cacheManager */ $cacheManager = $this->xpdo->getCacheManager(); if (empty($cacheManager)) return; $c = $this->xpdo->newQuery('modContext'); $c->select($this->xpdo->escape('key')); $options[xPDO::OPT_CACHE_KEY] = $this->getOption('cache_media_sources_key', $options, 'media_sources'); $options[xPDO::OPT_CACHE_HANDLER] = $this->getOption('cache_media_sources_handler', $options, $this->getOption(xPDO::OPT_CACHE_HANDLER, $options)); $options[xPDO::OPT_CACHE_FORMAT] = (integer) $this->getOption('cache_media_sources_format', $options, $this->getOption(xPDO::OPT_CACHE_FORMAT, $options, xPDOCacheManager::CACHE_PHP)); $options[xPDO::OPT_CACHE_ATTEMPTS] = (integer) $this->getOption('cache_media_sources_attempts', $options, $this->getOption(xPDO::OPT_CACHE_ATTEMPTS, $options, 10)); $options[xPDO::OPT_CACHE_ATTEMPT_DELAY] = (integer) $this->getOption('cache_media_sources_attempt_delay', $options, $this->getOption(xPDO::OPT_CACHE_ATTEMPT_DELAY, $options, 1000)); if ($c->prepare() && $c->stmt->execute()) { while ($row = $c->stmt->fetch(PDO::FETCH_ASSOC)) { if ($row && !empty($row['key'])) { $cacheManager->delete($row['key'].'/source',$options); } } } } }