manager/controllers/default/resource/resource.class.php
<?php
/*
* This file is part of MODX Revolution.
*
* Copyright (c) MODX, LLC. All Rights Reserved.
*
* For complete copyright and license information, see the COPYRIGHT and LICENSE
* files found in the top-level directory of this distribution.
*/
/**
* Base controller class for Resources
*
* @package modx
* @subpackage manager.controllers
*/
abstract class ResourceManagerController extends modManagerController {
public $resourceArray = array();
public $onDocFormRender = '';
public $ctx = 'web';
/** @var modContext $context */
public $context;
/** @var modResource $resource */
public $resource;
/** @var modResource $resource */
public $parent = null;
/** @var string $resourceClass */
public $resourceClass = 'modDocument';
/** @var array $tvCounts */
public $tvCounts = array();
/** @var array $rteFields */
public $rteFields = array();
/** @var modRegister $reg */
protected $reg;
public $canPublish = true;
public $canSave = true;
public $canDuplicate = true;
public $canDelete = true;
public $canEdit = true;
public $canCreate = true;
public $canCreateRoot = true;
/**
* Return the appropriate Resource controller class based on the class_key request parameter
*
* @static
* @param modX $modx A reference to the modX instance
* @param string $className The controller class name that is attempting to be loaded
* @param array $config An array of configuration options for the action
* @return modManagerController The proper controller class
*/
public static function getInstance(modX &$modx,$className,array $config = array()) {
$resourceClass = 'modDocument';
$isDerivative = false;
if (!empty($_REQUEST['class_key'])) {
$isDerivative = true;
$resourceClass = in_array($_REQUEST['class_key'],array('modDocument','modResource')) ? 'modDocument' : $_REQUEST['class_key'];
if ($resourceClass == 'modResource') $resourceClass = 'modDocument';
} else if (!empty($_REQUEST['id']) && $_REQUEST['id'] != 'undefined' && strlen($_REQUEST['id']) === strlen((integer)$_REQUEST['id'])) {
/** @var modResource $resource */
$resource = $modx->getObject('modResource', array('id' => $_REQUEST['id']));
if ($resource && !in_array($resource->get('class_key'),array('modDocument','modResource'))) {
$isDerivative = true;
$resourceClass = $resource->get('class_key');
} else if ($resource && $resource->get('class_key') == 'modResource') { /* fix improper class key */
$resource->set('class_key','modDocument');
$resource->save();
}
}
if ($isDerivative) {
$resourceClass = str_replace(array('../','..','/','\\'),'',$resourceClass);
if (!class_exists($resourceClass) && !$modx->loadClass($resourceClass)) {
$resourceClass = 'modDocument';
}
$delegateView = $modx->call($resourceClass,'getControllerPath',array(&$modx));
$action = strtolower(str_replace(array('Resource','ManagerController'),'',$className));
$className = str_replace('mod','',$resourceClass).ucfirst($action).'ManagerController';
$controllerFile = $delegateView.$action.'.class.php';
if (!file_exists($controllerFile)) {
// We more than likely are using a custom manager theme without overridden controller, let's try with the default theme
$theme = $modx->getOption('manager_theme', null, 'default');
$modx->setOption('manager_theme', 'default');
$delegateView = $modx->call($resourceClass, 'getControllerPath', array(&$modx));
$controllerFile = $delegateView.$action.'.class.php';
// Restore custom theme (so we don't process/use default theme assets)
$modx->setOption('manager_theme', $theme);
}
require_once $controllerFile;
}
$controller = new $className($modx,$config);
$controller->resourceClass = $resourceClass;
return $controller;
}
/**
* Used to set values on the resource record sent to the template for derivative classes
*
* @return void
*/
public function prepareResource() {}
/**
* Specify the language topics to load
* @return array
*/
public function getLanguageTopics() {
return array('resource');
}
/**
* Setup permissions for this page
* @return void
*/
public function setPermissions() {
if ($this->canSave) {
$this->canSave = $this->resource->checkPolicy('save');
}
$this->canEdit = $this->modx->hasPermission('edit_document');
$this->canCreate = $this->modx->hasPermission('new_document');
$this->canPublish = $this->modx->hasPermission('publish_document');
$this->canDelete = ($this->modx->hasPermission('delete_document') && $this->resource->checkPolicy(array('save' => true, 'delete' => true)));
$this->canDuplicate = ($this->modx->hasPermission('resource_duplicate') && $this->resource->checkPolicy('save'));
$this->canCreateRoot = $this->modx->hasPermission('new_document_in_root');
}
/**
* Get and set the parent for this resource
* @return string The pagetitle of the parent
*/
public function setParent() {
/* handle default parent */
$parentName = $this->context->getOption('site_name', '', $this->modx->_userConfig);
$parentId = !empty($this->scriptProperties['parent']) ? $this->scriptProperties['parent'] : $this->resource->get('parent');
if ($parentId == 0) {
$parentName = $this->context->getOption('site_name', '', $this->modx->_userConfig);
} else {
$this->parent = $this->modx->getObject('modResource',$parentId);
if ($this->parent !== null) {
$parentName = $this->parent->get('pagetitle');
$this->resource->set('parent',$parentId);
}
}
if ($this->parent === null) {
$this->parent = $this->modx->newObject($this->resourceClass);
$this->parent->set('id',0);
$this->parent->set('parent',0);
}
return $parentName;
}
/**
* Fire any pre-render events
* @return array|bool|string
*/
public function firePreRenderEvents() {
$resourceId = !empty($this->resource) && ($this->resource instanceof $this->resourceClass) ? $this->resource->get('id') : (!empty($this->scriptProperties['id']) ? $this->scriptProperties['id'] : 0);
$properties = array(
'id' => $resourceId,
'mode' => !empty($resourceId) ? modSystemEvent::MODE_UPD : modSystemEvent::MODE_NEW,
);
if (!empty($resourceId)) {
$properties['resource'] =& $this->resource;
}
$onDocFormPrerender = $this->modx->invokeEvent('OnDocFormPrerender',$properties);
if (is_array($onDocFormPrerender)) {
$onDocFormPrerender = implode('',$onDocFormPrerender);
}
$this->setPlaceholder('onDocFormPrerender',$onDocFormPrerender);
return $onDocFormPrerender;
}
/**
* Fire any render events
* @return string
*/
public function fireOnRenderEvent() {
$resourceId = $this->resource->get('id');
$this->onDocFormRender = $this->modx->invokeEvent('OnDocFormRender',array(
'id' => $resourceId,
'resource' => &$this->resource,
'mode' => !empty($resourceId) ? modSystemEvent::MODE_UPD : modSystemEvent::MODE_NEW,
));
if (is_array($this->onDocFormRender)) $this->onDocFormRender = implode('',$this->onDocFormRender);
$this->onDocFormRender = str_replace(array('"',"\n","\r"),array('\"','',''),$this->onDocFormRender);
$this->setPlaceholder('onDocFormRender',$this->onDocFormRender);
return $this->onDocFormRender;
}
/**
* Initialize a RichText Editor, if set
*
* @return void
*/
public function loadRichTextEditor() {
/* register JS scripts */
$rte = isset($this->scriptProperties['which_editor']) ? $this->scriptProperties['which_editor'] : $this->context->getOption('which_editor', '', $this->modx->_userConfig);
$this->setPlaceholder('which_editor',$rte);
/* Set which RTE if not core */
if ($this->context->getOption('use_editor', false, $this->modx->_userConfig) && !empty($rte)) {
/* invoke OnRichTextEditorRegister event */
$textEditors = $this->modx->invokeEvent('OnRichTextEditorRegister');
$this->setPlaceholder('text_editors',$textEditors);
$this->rteFields = array('ta');
$this->setPlaceholder('replace_richtexteditor',$this->rteFields);
/* invoke OnRichTextEditorInit event */
$resourceId = $this->resource->get('id');
$onRichTextEditorInit = $this->modx->invokeEvent('OnRichTextEditorInit',array(
'editor' => $rte,
'elements' => $this->rteFields,
'id' => $resourceId,
'resource' => &$this->resource,
'mode' => !empty($resourceId) ? modSystemEvent::MODE_UPD : modSystemEvent::MODE_NEW,
));
if (is_array($onRichTextEditorInit)) {
$onRichTextEditorInit = implode('',$onRichTextEditorInit);
$this->setPlaceholder('onRichTextEditorInit',$onRichTextEditorInit);
}
}
}
/**
* Get and set the context for this resource
*
* @return modContext
*/
public function setContext() {
if(!empty($this->scriptProperties['context_key'])) {
$this->ctx = $this->modx->stripTags($this->scriptProperties['context_key']);
} else {
$this->ctx = !empty($this->resource) ? $this->resource->get('context_key') : $this->modx->getOption('default_context');
}
$this->context = $this->modx->getContext($this->ctx);
if (!$this->context) {
$this->ctx = '';
}
$this->setPlaceholder('_ctx',$this->ctx);
return $this->context;
}
/**
* Load the TVs for the Resource
*
* @param array $reloadData resource data passed if reloading
* @return string The TV editing form
*/
public function loadTVs($reloadData = array()) {
$this->setPlaceholder('wctx',$this->resource->get('context_key'));
$_GET['wctx'] = $this->resource->get('context_key');
$this->fireOnTVFormRender();
/* get categories */
$c = $this->modx->newQuery('modCategory');
$c->sortby($this->modx->escape('rank'), 'ASC');
$c->sortby($this->modx->escape('category'),'ASC');
$cats = $this->modx->getCollection('modCategory',$c);
$categories = array();
/** @var modCategory $cat */
foreach ($cats as $cat) {
$categories[$cat->get('id')] = $cat->toArray();
$categories[$cat->get('id')]['tvs'] = array();
$categories[$cat->get('id')]['tvCount'] = 0;
}
$categories[0] = array(
'id' => 0,
'category' => ucfirst($this->modx->lexicon('uncategorized')),
'tvs' => array(),
'tvCount' => 0,
);
$tvMap = array();
$hidden = array();
$templateId = $this->resource->get('template');
if ($templateId && ($template = $this->modx->getObject('modTemplate', $templateId))) {
if ($template) {
$c = $this->modx->newQuery('modTemplateVar');
$c->query['distinct'] = 'DISTINCT';
$c->leftJoin('modCategory','Category');
$c->innerJoin('modTemplateVarTemplate','TemplateVarTemplate',array(
'TemplateVarTemplate.tmplvarid = modTemplateVar.id',
'TemplateVarTemplate.templateid' => $templateId,
));
$c->leftJoin('modTemplateVarResource','TemplateVarResource',array(
'TemplateVarResource.tmplvarid = modTemplateVar.id',
'TemplateVarResource.contentid' => $this->resource->get('id'),
));
$c->select($this->modx->getSelectColumns('modTemplateVar', 'modTemplateVar'));
$c->select($this->modx->getSelectColumns('modCategory', 'Category', 'cat_', array('category')));
if(empty($reloadData)) {
$c->select($this->modx->getSelectColumns('modTemplateVarResource', 'TemplateVarResource', '', array('value')));
}
$c->select($this->modx->getSelectColumns('modTemplateVarTemplate', 'TemplateVarTemplate', '', array('rank')));
$c->sortby('cat_category,TemplateVarTemplate.rank,modTemplateVar.rank','ASC');
$tvs = $this->modx->getCollection('modTemplateVar',$c);
$reloading = !empty($reloadData) && count($reloadData) > 0;
$this->setPlaceholder('tvcount',count($tvs));
/** @var modTemplateVar $tv */
foreach ($tvs as $tv) {
if (!$tv->checkResourceGroupAccess(null,'mgr')) {
continue;
}
$v = '';
$tv->set('inherited', false);
/** @var int $cat */
$cat = (int)$tv->get('category');
$tvid = $tv->get('id');
if($reloading && array_key_exists('tv'.$tvid, $reloadData)) {
$v = $reloadData['tv'.$tvid];
$tv->set('value', $v);
} else {
$default = $tv->processBindings($tv->get('default_text'),$this->resource->get('id'));
if (strpos($tv->get('default_text'),'@INHERIT') > -1 && (strcmp($default,$tv->get('value')) === 0 || $tv->get('value') === null)) {
$tv->set('inherited',true);
}
if ($tv->get('value') === null) {
$v = $default;
$tv->set('value',$v);
}
}
if ($tv->get('type') == 'richtext') {
$this->rteFields = array_merge($this->rteFields,array(
'tv' . $tv->get('id'),
));
}
$inputForm = $tv->renderInput($this->resource, array('value'=> $v));
if (empty($inputForm)) continue;
$tv->set('formElement',$inputForm);
if ($tv->get('type') != 'hidden') {
if (!isset($categories[$cat]['tvs']) || !is_array($categories[$cat]['tvs'])) {
$categories[$cat]['tvs'] = array();
$categories[$cat]['tvCount'] = 0;
}
/* add to tv/category map */
$tvMap[$tv->get('id')] = $tv->category;
/* add TV to category array */
$categories[$cat]['tvs'][] = $tv;
if ($tv->get('type') != 'hidden') {
$categories[$cat]['tvCount']++;
}
} else {
$hidden[] = $tv;
}
}
}
}
$finalCategories = array();
/** @var modCategory $category */
foreach ($categories as $n => $category) {
if (is_array($category)) {
$category['hidden'] = empty($category['tvCount']) ? true : false;
$ct = isset($category['tvs']) ? count($category['tvs']) : 0;
if ($ct > 0) {
$finalCategories[$category['id']] = $category;
$this->tvCounts[$n] = $ct;
}
}
}
$onResourceTVFormRender = $this->modx->invokeEvent('OnResourceTVFormRender',array(
'categories' => &$finalCategories,
'template' => $templateId,
'resource' => $this->resource->get('id'),
'tvCounts' => &$this->tvCounts,
'hidden' => &$hidden,
));
if (is_array($onResourceTVFormRender)) {
$onResourceTVFormRender = implode('',$onResourceTVFormRender);
}
$this->setPlaceholder('OnResourceTVFormRender',$onResourceTVFormRender);
$this->setPlaceholder('categories',$finalCategories);
$this->setPlaceholder('tvCounts',$this->modx->toJSON($this->tvCounts));
$this->setPlaceholder('tvMap',$this->modx->toJSON($tvMap));
$this->setPlaceholder('hidden',$hidden);
if (is_null($this->getPlaceholder('tvcount'))) {
$this->setPlaceholder('tvcount', 0);
}
if (!empty($this->scriptProperties['showCheckbox'])) {
$this->setPlaceholder('showCheckbox',1);
}
$tvOutput = $this->fetchTemplate('resource/sections/tvs.tpl');
if (!empty($this->tvCounts)) {
$this->setPlaceholder('tvOutput',$tvOutput);
}
return $tvOutput;
}
/**
* Set token for validating a request
*
* @return void
*/
public function setResourceToken() {
if(!isset($_SESSION['newResourceTokens']) || !is_array($_SESSION['newResourceTokens'])) {
$_SESSION['newResourceTokens'] = array();
}
$this->resourceArray['create_resource_token'] = uniqid('', true);
$_SESSION['newResourceTokens'][] = $this->resourceArray['create_resource_token'];
}
/**
* Fire the TV Form Render event
* @return mixed
*/
public function fireOnTVFormRender() {
$onResourceTVFormPrerender = $this->modx->invokeEvent('OnResourceTVFormPrerender',array(
'resource' => $this->resource->get('id'),
));
if (is_array($onResourceTVFormPrerender)) {
$onResourceTVFormPrerender = implode('',$onResourceTVFormPrerender);
}
$this->setPlaceholder('OnResourceTVFormPrerender',$onResourceTVFormPrerender);
return $onResourceTVFormPrerender;
}
protected function getReloadData() {
$modx =& $this->modx;
$scriptProperties =& $this->scriptProperties;
$reloadData = array();
// get reload data if reload token found in registry
if (array_key_exists('reload', $scriptProperties) && !empty($scriptProperties['reload'])) {
if(!isset($modx->registry)) {
$modx->getService('registry', 'registry.modRegistry');
}
/** @var modRegistry $modx->registry */
if(isset($modx->registry)) {
$modx->registry->addRegister('resource_reload', 'registry.modDbRegister', array('directory' => 'resource_reload'));
$this->reg = $modx->registry->resource_reload;
if($this->reg->connect()) {
$topic = '/resourcereload/' . $scriptProperties['reload'];
$this->reg->subscribe($topic);
$msgs = $this->reg->read(array('poll_limit'=> 1, 'remove_read'=> true));
if(is_array($msgs)) {
$reloadData = reset($msgs);
}
if(!is_array($reloadData)) {
$reloadData = array();
}
$this->reg->unsubscribe($topic);
}
}
}
return $reloadData;
}
public function getResourceGroups() {
$parentGroups = array();
if ($this->resource->get('id') == 0) {
$parent = $this->modx->getObject('modResource',$this->resource->get('parent'));
/** @var modResource $parent */
if ($parent) {
$parentResourceGroups = $parent->getMany('ResourceGroupResources');
/** @var modResourceGroupResource $parentResourceGroup */
foreach ($parentResourceGroups as $parentResourceGroup) {
$parentGroups[] = $parentResourceGroup->get('document_group');
}
$parentGroups = array_unique($parentGroups);
}
}
$this->resourceArray['resourceGroups'] = array();
$resourceGroups = $this->resource->getGroupsList(array('name' => 'ASC'),0,0);
/** @var modResourceGroup $resourceGroup */
foreach ($resourceGroups['collection'] as $resourceGroup) {
$access = (boolean) $resourceGroup->get('access');
if (!empty($parent) && $this->resource->get('id') == 0) {
$access = in_array($resourceGroup->get('id'),$parentGroups) ? true : false;
}
$resourceGroupArray = array(
$resourceGroup->get('id'),
$resourceGroup->get('name'),
$access,
);
$this->resourceArray['resourceGroups'][] = $resourceGroupArray;
}
return $this->resourceArray['resourceGroups'];
}
/**
* Get the Help URL
* @return string
*/
public function getHelpUrl() {
return 'Resources';
}
}