/** * @param string $cbUri The CB-URI (cbo;,,,) * @param SimpleXMLElement $sourceElem The XML element from which the URL is computed * @param TableInterface $data The data of the object for dynamic URL request values * @param int $id The id of the current row * @param bool $htmlspecialchars If htmlspecialchars should be made for this * @param bool $inPage URL target: true: html (full page), false: raw (only center component content) * @return string The URL */ function drawUrl($cbUri, SimpleXMLElement $sourceElem, $data, $id, $htmlspecialchars = true, $inPage = true) { global $_CB_framework; if (!Access::authorised($sourceElem)) { return null; } $ui = $_CB_framework->getUi(); $actionName = null; if (substr($cbUri, 0, 4) == 'cbo:') { $subTaskValue = substr($cbUri, 4); switch ($subTaskValue) { /** @noinspection PhpMissingBreakStatementInspection */ case 'newrow': // $id = 0; // fallthrough: no break on purpose. // $id = 0; // fallthrough: no break on purpose. case 'rowedit': //TBD this is duplicate of below $baseUrl = 'index.php'; if ($this->_options['view'] == 'editPlugin') { $task = $this->_options['view']; } else { $task = 'editrow'; } $baseUrl .= '?option=' . $this->_options['option'] . '&view=' . $task; if (isset($this->_options['pluginid'])) { $baseUrl .= '&cid=' . $this->_options['pluginid']; } $url = $baseUrl . '&table=' . $this->_tableBrowserModel->attributes('name') . '&action=editrow'; // below: . '&tid=' . $id; break; case 'saveorder': case 'editrows': case 'deleterows': case 'copyrows': case 'updaterows': case 'publish': case 'unpublish': case 'enable': case 'disable': default: $url = 'javascript:cbDoListTask(this, ' . "'" . addslashes($this->taskName(false)) . "','" . addslashes($this->subtaskName(false)) . "','" . addslashes($this->subtaskValue($subTaskValue, false)) . "','" . addslashes($this->fieldId('id', null, false)) . "'" . ");"; break; } } elseif (substr($cbUri, 0, 10) == 'cb_action:') { $actionName = substr($cbUri, 10); $action = $this->_actions->getChildByNameAttr('action', 'name', $actionName); if ($action) { if (!Access::authorised($action)) { return null; } $requestNames = explode(' ', $action->attributes('request')); $requestValues = explode(' ', $action->attributes('action')); $parametersValues = explode(' ', $action->attributes('parameters')); $baseUrl = 'index.php'; $baseUrl .= '?'; $baseRequests = array('option' => 'option', 'view' => 'view', 'cid' => 'pluginid'); $urlParams = array(); foreach ($baseRequests as $breq => $breqOptionsValue) { if (!(in_array($breq, $requestNames) || in_array($breq, $parametersValues)) && isset($this->_options[$breqOptionsValue])) { $urlParams[$breq] = $breq . '=' . $this->_options[$breqOptionsValue]; } } for ($i = 0, $n = count($requestNames); $i < $n; $i++) { $urlParams[$requestNames[$i]] = $requestNames[$i] . '=' . $requestValues[$i]; // other parameters = paramvalues added below } $url = $baseUrl . implode('&', $urlParams); } else { $url = "#action_not_defined:" . $actionName; } } else { $url = cbUnHtmlspecialchars($cbUri); } if (cbStartOfStringMatch($url, 'index.php')) { // get the parameters of action/link from XML : $parametersNames = explode(' ', $sourceElem->attributes('parameters')); $parametersValues = explode(' ', $sourceElem->attributes('paramvalues')); $parametersValuesTypes = explode(' ', $sourceElem->attributes('paramvaluestypes')); // generate current action (and parameters ?) as cbprevstate $cbprevstate = array(); foreach ($this->_options as $req => $act) { if ($req && $act && !in_array($req, array('cbprevstate'))) { $cbprevstate[] = $req . '=' . $act; } } $parametersNames[] = 'cbprevstate'; $parametersValues[] = "'" . base64_encode(implode('&', $cbprevstate)) . "'"; // finally generate URL: for ($i = 0, $n = count($parametersNames); $i < $n; $i++) { $nameOfVariable = $parametersValues[$i]; if ($nameOfVariable != '') { if (isset($parametersValuesTypes[$i]) && $parametersValuesTypes[$i]) { if ($parametersValuesTypes[$i] == 'sql:field') { if (is_callable(array($data, 'get'))) { $nameOfVariable = $data->get($nameOfVariable); } else { $nameOfVariable = $data->{$nameOfVariable}; } } else { // $nameOfVariable untouched } } elseif (substr($nameOfVariable, 0, 1) == "'" && substr($nameOfVariable, -1) == "'") { $nameOfVariable = substr($nameOfVariable, 1, -1); } else { if (is_callable(array($data, 'get'))) { $nameOfVariable = $data->get($nameOfVariable); } else { $nameOfVariable = $data->{$nameOfVariable}; } } $url .= '&' . $parametersNames[$i] . '=' . urlencode($nameOfVariable); } } if ($ui == 2) { $url = $_CB_framework->backendUrl($url, $htmlspecialchars, $inPage ? 'html' : 'component'); } else { $url = cbSef($url, $htmlspecialchars, $inPage ? 'html' : 'component'); } } elseif ($htmlspecialchars) { $url = htmlspecialchars($url); } return $url; }
/** * Parse list options for options, optgroups, and evaluate IF conditions * * @param string $name The name of the form element * @param SimpleXMLElement $node The xml element for the parameter * @param string $control_name The control name * @param array $options The base array of options to extend with parsed options * @param SimpleXMLElement[] $children The child xml elements for the parameter * @param bool $otgroups If optgroups should be added to the options array * @param string $value The value of the element * @param bool $ignoreClass If option classes should be ignored or not * @param int $index The option index */ function _list_options( $name, &$node, $control_name, &$options, $children, $otgroups = true, $value = null, $ignoreClass = false, &$index = 0 ) { $translate = $node->attributes( 'translate' ); if ( $children ) foreach ( $children as $option ) { $optTranslate = ( $option->attributes( 'translate' ) !== null ? $option->attributes( 'translate' ) : $translate ); if ( $option->getName() == 'option' ) { if ( ( $option->attributes( 'index' ) !== '' ) && ( $option->attributes( 'index' ) !== null ) ) { $val = $option->attributes( 'index' ); } else { $val = $option->attributes( 'value' ); } if ( ( $option->attributes( 'selectable' ) != 'false' ) || ( (string) $val === (string) $value ) ) { $label = $option->data(); $opt = $this->_list_make_option( $optTranslate, $val, ( $label !== '' ? $label : $val ), 'value', 'text', null, ( $ignoreClass ? null : RegistryEditView::buildClasses( $option ) ) ); $opt->id = $this->control_id( $control_name, $name ) . '__cbf' . $index; $options[] = $opt; $index++; } } elseif ( $otgroups && ( $option->getName() == 'optgroup' ) ) { if ( $optTranslate == 'no' ) { $label = $option->attributes( 'label' ); } else { $label = CBTxt::T( $option->attributes( 'label' ) ); } $opt = moscomprofilerHTML::makeOptGroup( $label, 'value', 'text', null, ( $ignoreClass ? null : RegistryEditView::buildClasses( $option ) ) ); $opt->id = $this->control_id( $control_name, $name ) . '__cbf' . $index; $options[] = $opt; $index++; $this->_list_options( $name, $node, $control_name, $options, $option->children(), $otgroups, $value, $ignoreClass, $index ); $options[] = moscomprofilerHTML::makeOptGroup( null ); } elseif ( $option->getName() == 'data' ) { // TODO: Replace this usage with _getFieldValues (aslo needs upgrading to support private/custom below) once it is refactored into RegistryEditView: global $_CB_database; if ( $option->attributes( 'type' ) == 'private' ) { $privateOptions = $this->_form_private( $name, $value, $option, $control_name ); if ( is_array( $privateOptions ) ) { $options = array_merge( $options, $privateOptions ); } } elseif ( $option->attributes( 'type' ) == 'custom' ) { $customOptions = $this->_form_custom( $name, $value, $option, $control_name ); if ( is_array( $customOptions ) ) { $options = array_merge( $options, $customOptions ); } } elseif ( $option->attributes( 'dataprocessed' ) != 'true' ) { $dataTable = $option->attributes( 'table' ); $xmlsql = new XmlQuery( $_CB_database, $dataTable, $this->_pluginParams ); $xmlsql->setExternalDataTypeValues( 'modelofdata', $this->_modelOfData[0] ); $xmlsql->process_orderby( $option->getElementByPath( 'orderby') ); // <data><orderby><field> fields $xmlsql->process_fields( $option->getElementByPath( 'rows') ); // <data><rows><field> fields $xmlsql->process_where( $option->getElementByPath( 'where') ); // <data><where><column> fields $groupby = $option->getElementByPath( 'groupby' ); $xmlsql->process_groupby( ( $groupby !== false ? $groupby : 'value' ) ); // <data><groupby><field> fields $fieldValuesInDb = $xmlsql->queryLoadObjectsList( $option ); // get the records $rows = $option->getElementByPath( 'rows'); // check for type="firstwords" /** @var $rows SimpleXMLElement|null */ if ( $rows ) { $textField = $rows->getChildByNameAttr( 'field', 'as', 'text' ); /** @var $textField SimpleXMLElement|null */ if ( $textField ) { if ( $textField->attributes( 'type' ) == 'firstwords' ) { $size = $textField->attributes( 'size' ); if ( ! $size ) { $size = 45; } foreach ( array_keys( $fieldValuesInDb ) as $k ) { $strippedContent = trim( $fieldValuesInDb[$k]->text ); if ( cbIsoUtf_strlen( $strippedContent ) > $size ) { $strippedContent = cbIsoUtf_substr( $strippedContent, 0, $size ) . '...'; } $fieldValuesInDb[$k]->text = $strippedContent; } } } } if ( $fieldValuesInDb ) { foreach ( array_keys( $fieldValuesInDb ) as $k ) { $dbOptTranslate = ( isset( $fieldValuesInDb[$k]->translate ) ? $fieldValuesInDb[$k]->translate : $optTranslate ); $options[] = $this->_list_make_option( $dbOptTranslate, $fieldValuesInDb[$k]->value, ( $fieldValuesInDb[$k]->text !== '' ? $fieldValuesInDb[$k]->text : $fieldValuesInDb[$k]->value ) ); } } } } elseif ( $option->getName() == 'if' ) { if ( $option->attributes( 'type' ) == 'showhide' ) { $ifName = ( $this->_htmlId( $control_name, $option ) . $option->attributes( 'operator' ) . $option->attributes( 'value' ) . $option->attributes( 'valuetype' ) ); $this->_jsif[$ifName]['element'] = $option; $this->_jsif[$ifName]['control_name'] = $control_name; $this->_jsif[$ifName]['ifname'] = $this->_htmlId( $control_name, $option ); $ifOptions = array(); $this->_list_options( $name, $node, $control_name, $ifOptions, $option->children(), $otgroups, $value, $ignoreClass, $index ); if ( $ifOptions ) foreach ( $ifOptions as $ifOption ) { if ( isset( $ifOption->id ) ) { $this->_jsif[$ifName]['show'][] = $ifOption->id; } } $options = array_merge( $options, $ifOptions ); } else { if ( $option->attributes( 'type' ) == 'permission' ) { $showInside = Access::authorised( $option ); } else { $showInside = $this->_evalIf( $option ); } if ( $showInside ) { $then = $option->getChildByNameAttributes( 'then' ); if ( $then ) { $insideParamToRender = $then; } else { $insideParamToRender = $option; } } else { $insideParamToRender = $option->getChildByNameAttributes( 'else' ); } if ( $insideParamToRender ) { $this->_list_options( $name, $node, $control_name, $options, $insideParamToRender->children(), $otgroups, $value, $ignoreClass, $index ); } } } } }
/** * Handles the backend plugin edition * * @param string $option * @param string $action * @param SimpleXMLElement $element * @param string $mode * @return string HTML * * @throws \LogicException */ public function drawView($option, $action, $element, $mode) { global $_CB_Backend_Menu; $ui = $this->clientId == 1 ? 2 : 1; $context = new Context(); $pluginParams = $context->getParams(); $interfaceUi = $ui == 2 ? 'admin' : 'frontend'; $adminActionsModel = $element->getChildByNameAttr('actions', 'ui', $interfaceUi); if (!$adminActionsModel) { $adminActionsModel = $element->getChildByNameAttr('actions', 'ui', 'all'); } if (!$adminActionsModel) { throw new \LogicException('No ' . $interfaceUi . ' actions defined in XML'); } // Check permission if specified: if (!Access::authorised($adminActionsModel)) { return CBTxt::T("Access to these actions is not authorized by the permissions of your user groups."); } // General-purpose extenders: $extenders = $adminActionsModel->xpath('extend'); /** @var SimpleXMLElement[] $extenders */ foreach ($extenders as $k => $extends) { $error = RegistryEditView::extendXMLnode($extenders[$k], $element, null, $context->getPluginObject()); if ($error) { echo $error; } } $found = false; $actionPath = array(); if ($action) { $actionsModel = $adminActionsModel->getChildByNameAttr('action', 'name', $action); $found = $actionsModel != null; if ($found) { $requests = explode(' ', $actionsModel->attributes('request')); $values = explode(' ', $actionsModel->attributes('action')); $actionPath = array(); for ($i = 0, $n = count($requests); $i < $n; $i++) { $actionPath[$requests[$i]] = $values[$i]; } } } if (!$found) { // EVENT: select the event from URL and compute the selected $actionPath $found = false; $actionsModel = null; foreach ($adminActionsModel->children() as $actionsModel) { /** @var SimpleXMLElement $actionsModel */ $request = $actionsModel->attributes('request'); if ($request) { $requests = explode(' ', $request); $values = explode(' ', $actionsModel->attributes('action')); $actionPath = array(); for ($i = 0, $n = count($requests); $i < $n; $i++) { $actionPath[$requests[$i]] = $this->input->get($requests[$i], null, GetterInterface::STRING); // Temporary fix for older versions of CBSubs before CBSubs 4.0.0 stable to avoid warnings on ajax version checks: if ($requests[$i] === 'view' && $actionPath['view'] === null) { $actionPath['view'] = $this->input->get('task', null, GetterInterface::STRING); } if ($actionPath[$requests[$i]] != $values[$i]) { break; } } if ($i == $n) { $found = true; break; } } } } if (!$found) { $actionPath = array(); // try finding first default one: if ($ui == 2) { $actionsModel = $adminActionsModel->getChildByNameAttr('action', 'request', ''); } if (!isset($actionsModel)) { return CBTxt::T('AHAWOW_REQUESTED_ACTION_NOT_DEFINED_IN_XML', "Requested action '[ACTION]' not defined in XML.", array('[ACTION]' => htmlspecialchars($action))); } } // Check permission if specified: if (!isset($actionsModel) || !Access::authorised($actionsModel)) { return CBTxt::T("This action is not authorized by the permissions of your user groups."); } if (!isset($actionPath['view'])) { $actionPath['view'] = $ui == 2 ? 'editPlugin' : ''; //TODO: 2nd should come from target routing } elseif ($actionPath['view'] != 'editPlugin') { $actionPath['act'] = ''; } // EVENT: fetch the input parameters from URL: $parametersNames = explode(' ', $actionsModel->attributes('requestparameters')); $parametersValues = array(); foreach ($parametersNames as $paraNam) { $parametersValues[$paraNam] = null; if (strpos($paraNam, '[') === false) { if (trim($paraNam)) { $parametersValues[$paraNam] = $this->input->get($paraNam, '', GetterInterface::STRING); } } else { $matches = null; preg_match_all('/(.*)(?:\\[(.*)\\])+/', $paraNam, $matches); if (is_array($matches) && count($matches) >= 3 && count($matches[2]) >= 1) { $parametersValues[$paraNam] = $this->input->get($matches[1][0] . '.' . $matches[2][0], null, GetterInterface::STRING); } } } $keyValues = array(); // Action-specific general extenders: $extenders = $adminActionsModel->xpath('actionspecific/extend'); /** @var SimpleXMLElement[] $extenders */ foreach ($extenders as $k => $extends) { $error = RegistryEditView::extendXMLnode($extenders[$k], $element, $actionsModel, $context->getPluginObject()); if ($error) { echo $error; } } // First extend what can be extended so the showview's below have a complete XML tree: /** @var $actionItem SimpleXMLElement */ foreach ($actionsModel->xpath('extend') as $actionItem) { $error = RegistryEditView::extendXMLnode($actionItem, $element, $actionsModel, $context->getPluginObject()); if ($error) { echo $error; } } /** @var $actionItem SimpleXMLElement */ foreach ($actionsModel->children() as $actionItem) { // CONTROLLER: select the controller: switch ($actionItem->getName()) { case 'extend': // Treated just above. break; case 'showview': $viewName = $actionItem->attributes('view'); $showviewType = $actionItem->attributes('type'); $viewMode = $actionItem->attributes('mode'); // MODEL: load data to view: $dataModel = $actionItem->getElementByPath('data'); if ($dataModel) { $dataModelType = $dataModel->attributes('type'); $cbDatabase = $this->db; if (in_array($dataModelType, array('sql:row', 'sql:multiplerows', 'sql:field', 'parameters'))) { $xmlsql = new XmlQuery($cbDatabase, null, $pluginParams); $data = $xmlsql->loadObjectFromData($dataModel); if ($data === null) { return 'showview::sql:row: load failed: ' . $cbDatabase->getErrorMsg(); } $dataModelValueName = $dataModel->attributes('value'); $dataModelValueType = $dataModel->attributes('valuetype'); // if the value of key is a parameter name, replace it with the corresponding parameter: $dataModelValueTypeArray = explode(':', $dataModelValueType); if ($dataModelValueTypeArray[0] == 'request') { if (isset($parametersValues[$dataModelValueName])) { $dataModelValue = $parametersValues[$dataModelValueName]; // database escaping to int is done at request time $keyValues[$dataModelValueName] = $dataModelValue; unset($parametersValues[$dataModelValueName]); } else { echo sprintf('showview::sql::row %s: request %s not in parameters of action.', $dataModel->attributes('name'), $dataModelValueName); } } if ($dataModelType == 'sql:field') { $data = new Registry($data); } } elseif ($dataModelType == 'class') { $dataModelClass = $dataModel->attributes('class'); $dataModelValue = $dataModel->attributes('value'); $dataModelValueName = $dataModelValue; $dataModelValueType = $dataModel->attributes('valuetype'); $dataModelValueTypeArray = explode(':', $dataModelValueType); if ($dataModelValueTypeArray[0] == 'request') { if (isset($parametersValues[$dataModelValueName])) { $dataModelValue = $parametersValues[$dataModelValueName]; $keyValues[$dataModelValueName] = $dataModelValue; unset($parametersValues[$dataModelValueName]); } else { echo sprintf('showview::sql::row %s: request %s not in parameters of action.', $dataModel->attributes('name'), $dataModelValue); } } if (strpos($dataModelClass, '::') === false) { $data = new $dataModelClass($cbDatabase); // normal clas="className" /** @var $data TableInterface */ $data->load($dataModelValue); } else { $dataModelSingleton = explode('::', $dataModelClass); // class object loader from singleton: class="loaderClass::loadStaticMethor" with 1 parameter, the key value. if (is_callable($dataModelSingleton)) { if (is_callable(array($dataModelSingleton[0], 'getInstance'))) { $instance = call_user_func_array(array($dataModelSingleton[0], 'getInstance'), array(&$cbDatabase)); $rows = call_user_func_array(array($instance, $dataModelSingleton[1]), array($dataModelValue)); } else { $rows = call_user_func_array($dataModelSingleton, array($dataModelValue)); } } else { echo sprintf('showview::class %s: missing singleton class creator %s.', $dataModel->attributes('name'), $dataModelClass); $std = new \stdClass(); $rows = array($std); } $data = $rows[0]; } } else { $data = null; echo 'showview: Data model type ' . $dataModelType . ' is not implemented !'; } } else { if ($this->_data instanceof TableInterface || $this->_data instanceof \comprofilerDBTable) { $data = $this->_data; $dataModelType = 'sql:row'; } elseif ($this->_data instanceof ParamsInterface) { $data = $this->_data; $dataModelType = 'sql:row'; } else { $data = null; $dataModelType = null; } } // VIEW: select view: $allViewsModels = $element->getElementByPath('views'); if ($viewName && (!$showviewType || $showviewType == 'view')) { ////// $viewModel = $allViewsModels->getChildByNameAttributes( 'view', array( 'name' => $viewName ) ); $xpathUi = '/*/views/view[@ui="' . $interfaceUi . '" and @name="' . $viewName . '"]'; $xpathAll = '/*/views/view[@ui="all" and @name="' . $viewName . '"]'; $viewModel = $element->xpath($xpathUi); if (!$viewModel) { $viewModel = $element->xpath($xpathAll); } if (!$viewModel) { $viewModel = RegistryEditView::xpathWithAutoLoad($element, $xpathUi); } if (!$viewModel) { $viewModel = RegistryEditView::xpathWithAutoLoad($element, $xpathAll); } /* if ( ! $viewModel ) { $viewModel = RegistryEditView::xpathWithAutoLoad( $element, '/ * / views/view[not(@ui) and @name="' . $viewName . '"]' ); } */ if ($viewModel) { $viewModel = $viewModel[0]; } else { return 'XML:showview: View ' . $viewName . ' not defined in ui ' . $interfaceUi . ' in XML'; } } elseif ($showviewType == 'xml') { // e.g.: <showview name="gateway_paymentstatus_information" mode="view" type="xml" file="processors/{payment_method}/edit.gateway" path="/*/views/view[@name="paymentstatusinformation"]" mandatory="false" /> $fromNode = $actionItem->attributes('path'); $fromFile = $actionItem->attributes('file'); if ($fromNode && $fromFile !== null) { // $this->substituteName( $fromFile, true ); // $this->substituteName( $fromNode, false ); $fromFile = $context->getPluginPath() . '/' . $fromFile . '.xml'; if ($fromFile === '' || is_readable($fromFile)) { if ($fromFile === '') { $fromRoot = $element; } else { $fromRoot = new SimpleXMLElement($fromFile, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0), true); } $viewModel = $fromRoot->xpath($fromNode); if (!$viewModel) { trigger_error('Admin:showview: View ' . $viewName . ': file ' . $fromFile . ', path: ' . $fromNode . ' does not exist or is empty.', E_USER_NOTICE); } $viewModel = $viewModel[0]; } else { throw new \LogicException('Admin:showview: View ' . $viewName . ': file ' . $fromFile . ' does not exist or is not readable.'); } } else { throw new \LogicException('Admin:showview: View ' . $viewName . ' file or path not defined..', E_USER_NOTICE); } } else { throw new \LogicException('Admin:showview: View ' . $viewName . ' not of supported type.', E_USER_NOTICE); } $viewUi = $viewModel->attributes('ui'); if ($viewUi & $viewUi != 'all' && $viewUi != $interfaceUi) { throw new \LogicException('showview: View ' . $viewName . ' not allowed for ' . $interfaceUi); } $extendedParser = $allViewsModels->getElementByPath('extendxmlparser'); $actionPath = array_merge($actionPath, $keyValues); $options = array_merge($this->getBaseOptions(), $actionPath, $parametersValues); if ($ui == 2) { $options = array_merge($options, $actionPath, $parametersValues); } $cbprevstate = $this->input->get('cbprevstate', null, GetterInterface::STRING); $params = new RegistryEditController($this->input, $this->db, new Registry(), $viewModel, $element, $context->getPluginObject()); $displayData = $this->bindInput($viewMode, $data); // Set the parameters with the $displayData : $registry = new Registry(); $registry->load($displayData); $registry->setStorage($displayData); $params->setRegistry($registry); $params->setPluginParams($pluginParams); $params->setOptions($options); if ($extendedParser) { $params->setExtendedViewParser($extendedParser); } $extenders = $allViewsModels->xpath('extend'); foreach ($extenders as $extends) { RegistryEditView::extendXMLnode($extends, $element, $actionsModel, $context->getPluginObject()); } $viewType = $viewModel->attributes('type'); switch ($viewType) { case 'params': if ($mode == 'edit') { if ($viewMode == 'edit' || $viewMode == 'show') { $viewTypeMode = $viewMode == 'edit' ? 'param' : 'view'; if ($ui == 2) { $htmlOutput = $this->input->get('no_html', 0, GetterInterface::COMMAND) != 1 && $this->input->get('format', null, GetterInterface::COMMAND) != 'raw'; ActionViewAdmin::editPluginView($options, $actionPath, $viewModel, $displayData, $params, $context->getPluginObject(), $viewTypeMode, $cbprevstate, $htmlOutput); $settings = null; $html = null; } else { /** @global \stdClass $_CB_Backend_Menu : 'show' : only displays close button, 'edit' : special close button */ global $_CB_Backend_Menu; $_CB_Backend_Menu = new \stdClass(); $html = ''; outputCbTemplate(); outputCbJs(); // $_CB_framework->outputCbJQuery( '' ); initToolTip(); $htmlFormatting = $viewModel->attributes('viewformatting'); if (!$htmlFormatting) { global $ueConfig; if (isset($ueConfig['use_divs']) && $ueConfig['use_divs'] == 1) { $htmlFormatting = 'div'; } else { $htmlFormatting = 'table'; } } $settings = $params->draw(null, null, null, null, null, null, false, $viewTypeMode, $htmlFormatting); } if ($ui == 2) { $_CB_Backend_Menu->mode = $viewMode; // Implemented in lower level in RegistryEditView: $toolbarMenu = $viewModel->getElementByPath( 'toolbarmenu' ); } if ($ui != 2) { $actionView = new ActionView(); $buttonSaveText = $actionsModel->attributes('label'); if (!$buttonSaveText) { $buttonSaveText = 'Save'; } $buttonSaveText = CBTxt::Th($buttonSaveText); // CBTxt::Th("Save"); For translation strings extraction $warning = null; if ($viewTypeMode == 'param') { $settings .= '<div class="cbControlButtonsLine">' . "\n\t" . '<span class="cb_button_wrapper">' . '<button type="submit" name="actbutton" value="' . 'save' . $action . '" class="button cbregButton cbregSaveButton">' . $buttonSaveText . '</button>' . '</span>' . "\n\t" . '</div>' . "\n"; $postedActionPath = $actionPath; unset($postedActionPath['view']); $formHiddens = array_merge($this->getBaseOptions(), array('act' => 'save' . $action), $postedActionPath); } else { $formHiddens = null; } $html .= $actionView->drawForm($settings, $warning, $formHiddens, array_merge($this->_getParams, array('act' => $action)), RegistryEditView::buildClasses($viewModel)); return $html; } } else { echo 'showview::params: mode is ' . $mode . ' but view mode is ' . $viewMode . ' instead of edit.'; } } elseif (in_array($mode, array('apply', 'save', 'savenew', 'savecopy'))) { $this->savePluginView($options, $actionPath, $keyValues, $parametersValues, $viewModel, $data, $params, $mode, $dataModelType, $context->getPluginObject(), $dataModel, $pluginParams, $cbprevstate, $ui); if ($ui == 2 && $mode == 'apply') { // We arrive here only in case of saving error, as redirect (performed in savePluginView) would loose the inputs: return $this->drawView($option, $action, $element, 'edit'); } } else { echo 'showview::params: view type params mode ' . $mode . ' is not implemented !'; } break; default: echo 'showview::not-params: type of view ' . $viewType . ' is not implemented !'; break; } break; default: echo 'action::not-showview: child xml element "' . $actionItem->getName() . '" of action is not implemented !'; break; } } return null; }
/** * Renders as ECHO HTML code of a table * * @param SimpleXMLElement $modelView * @param array $modelRows * @param DrawController $controllerView * @param array $options * @param string $viewType ( 'view', 'param', 'depends': means: <param> tag => param, <field> tag => view ) */ protected function renderList(&$modelView, &$modelRows, &$controllerView, &$options, $viewType = 'view') { global $_CB_framework; static $JS_loaded = 0; $pluginParams = $this->_pluginParams; $renderer = new RegistryEditView($this->input, $this->_db, $pluginParams, $this->_types, $this->_actions, $this->_views, $this->_pluginObject, $this->_tabid); $renderer->setParentView($modelView); $renderer->setModelOfDataRows($modelRows); $name = $modelView->attributes('name'); $listFieldsRows = $modelView->getElementByPath('listfields/rows'); $listFieldsPager = $modelView->getElementByPath('listfields/paging'); $filtersArray = $controllerView->filters($renderer, 'table'); $batchArray = $controllerView->batchprocess($renderer, 'table'); outputCbJs(); $tableLabel = trim(CBTxt::Th($modelView->attributes('label'))); $tableMenu = $modelView->getElementByPath('tablemenu'); if (!$JS_loaded++) { if ($controllerView->pageNav !== null) { $searchButtonJs = $controllerView->pageNav->limitstartJs(0); } else { $searchButtonJs = 'cbParentForm( this ).submit();'; } $js = "\$( '.cbTableHeader' ).on( 'click', '.cbTableHeaderExpand', function() {" . "\$( this ).removeClass( 'btn-default cbTableHeaderExpand' ).addClass( 'btn-primary cbTableHeaderCollapse' );" . "\$( this ).find( '.fa' ).removeClass( 'fa-caret-down' ).addClass( 'fa-caret-up' );" . "\$( '.' + \$( this ).data( 'toggle' ) ).slideDown();" . "});" . "\$( '.cbTableHeader' ).on( 'click', '.cbTableHeaderCollapse', function() {" . "var toggle = \$( this ).data( 'toggle' );" . "\$( this ).removeClass( 'btn-primary cbTableHeaderCollapse' ).addClass( 'btn-default cbTableHeaderExpand' );" . "\$( this ).find( '.fa' ).removeClass( 'fa-caret-up' ).addClass( 'fa-caret-down' );" . "\$( '.' + toggle ).slideUp();" . "if ( toggle == 'cbBatchTools' ) {" . "\$( '.' + toggle ).find( 'input,textarea,select' ).val( '' );" . "if ( \$.fn.cbselect ) {" . "\$( '.' + toggle ).find( 'select.cbSelect2' ).each( function() {" . "\$( this ).cbselect( 'set', '' );" . "});" . "}" . "} else {" . "\$( '.' + toggle ).find( 'input,textarea,select' ).each( function() {" . "var value = null;" . "if ( \$( this ).hasClass( 'cbSelect2' ) ) {" . "if ( \$.fn.cbselect ) {" . "value = \$( this ).cbselect( 'get' );" . "} else {" . "value = \$( this ).val();" . "}" . "} else {" . "value = \$( this ).val();" . "}" . "if ( ( value != null ) && ( value != '' ) ) {" . "\$( '.cbTableHeaderClear' ).click(); return;" . "}" . "});" . "}" . "});" . "\$( '.cbTableHeader' ).on( 'click', '.cbTableHeaderClear', function() {" . "\$( '.cbTableHeader' ).find( 'input,textarea,select' ).val( '' );" . "if ( \$.fn.cbselect ) {" . "\$( '.cbTableHeader' ).find( 'select.cbSelect2' ).each( function() {" . "\$( this ).cbselect( 'set', '' );" . "});" . "}" . $searchButtonJs . "});" . "\$( '.cbTableBrowserRowsHeader' ).on( 'click', '.cbTableBrowserSort', function() {" . "\$( '.cbTableHeader' ).find( '.cbTableBrowserSorting > select' ).val( \$( this ).data( 'table-sort' ) ).change();" . "});" . ($this->_filtered ? "\$( '.cbSearchToolsToggle' ).click();" : null); $_CB_framework->outputCbJQuery($js); } $return = '<div class="table-responsive cbTableBrowserDiv' . ($name ? ' cbDIV' . htmlspecialchars($name) : null) . '">'; if ($tableLabel || $tableMenu || $controllerView->hasSearchFields() || $controllerView->hasOrderbyFields() || count($filtersArray) > 0 || count($batchArray) > 0) { $return .= '<table class="table table-noborder cbTableBrowserHeader' . ($name ? ' cbTA' . htmlspecialchars($name) : null) . '">' . '<thead>' . '<tr class="cbTableHeader">'; if ($tableLabel || $tableMenu) { $return .= '<th style="width: 10%;" class="text-left cbTableBrowserLabel' . ($name ? ' cbTH' . htmlspecialchars($name) : null) . '">' . ($tableLabel ? $tableLabel : null); if ($tableMenu) { $menuIndex = 1; $return .= $tableLabel ? '<div><small>[ ' : null; foreach ($tableMenu->children() as $menu) { /** @var SimpleXMLElement $menu */ $menuAction = $menu->attributes('action'); $menuLabelHtml = trim(CBTxt::Th(htmlspecialchars($menu->attributes('label')))); $menuDesc = $menu->attributes('description'); if ($menuDesc) { $menuDesc = ' title="' . trim(htmlspecialchars(CBTxt::T($menuDesc))) . '"'; } $return .= $menuIndex > 1 ? ' - ' : null; if ($menuAction) { $data = null; $link = $controllerView->drawUrl($menuAction, $menu, $data, 0, true); if ($link) { $return .= '<a href="' . $link . '"' . $menuDesc . '>' . $menuLabelHtml . '</a>'; } } elseif ($menuDesc) { $return .= '<span' . $menuDesc . '>' . $menuLabelHtml . '</span>'; } else { $return .= $menuLabelHtml; } $menuIndex++; } $return .= $tableLabel ? ' ]</small></div>' : null; } $return .= '</th>'; } if ($controllerView->hasSearchFields() || $controllerView->hasOrderbyFields() || count($filtersArray) > 0 || count($batchArray) > 0) { $return .= '<th class="cbTableHeaderTools">' . '<div class="text-left clearfix cbTableBrowserTools">'; if ($controllerView->hasSearchFields()) { $return .= $controllerView->quicksearchfields(); } if (count($filtersArray) > 0) { if ($controllerView->hasSearchFields()) { $return .= ' '; } $return .= '<button type="button" class="btn btn-default cbSearchToolsToggle cbTableHeaderExpand" data-toggle="cbSearchTools">' . CBTxt::Th('Search Tools') . ' <span class="fa fa-caret-down"></span></button>'; } if (count($batchArray) > 0) { if (count($filtersArray) > 0 || $controllerView->hasSearchFields()) { $return .= ' '; } $return .= '<button type="button" class="btn btn-default cbBatchToolsToggle cbTableHeaderExpand" data-toggle="cbBatchTools">' . CBTxt::Th('Batch Tools') . ' <span class="fa fa-caret-down"></span></button>'; } $return .= ' <button type="button" class="btn btn-default cbTableHeaderClear">' . CBTxt::Th('Clear') . '</button>'; if ($controllerView->hasOrderbyFields()) { if (count($filtersArray) > 0 || count($batchArray) > 0 || $controllerView->hasSearchFields()) { $return .= ' '; } $return .= '<span class="text-right pull-right cbTableBrowserSorting">' . $controllerView->orderbyfields() . '</span>'; } $return .= '</div>'; if (count($filtersArray) > 0) { $return .= '<fieldset class="cbFilters cbSearchTools cbFieldset">' . '<legend>' . CBTxt::Th('Search Tools') . '</legend>' . implode(' ', $filtersArray) . '</fieldset>'; } if (count($batchArray) > 0) { $return .= '<fieldset class="cbBatchProcess cbBatchTools cbFieldset">' . '<legend>' . CBTxt::Th('Batch Tools') . '</legend>' . implode(' ', $batchArray) . '</fieldset>'; } $return .= '</th>'; } $return .= '</tr>' . '</thead>' . '</table>'; } if ($listFieldsRows) { $columnCount = 0; $return .= '<table class="table table-hover cbTableBrowserRows' . ($name ? ' cbTL' . htmlspecialchars($name) : null) . '">' . '<thead>' . '<tr class="cbTableBrowserRowsHeader">'; foreach ($listFieldsRows->children() as $field) { /** @var SimpleXMLElement $field */ if ($field->attributes('type') != 'hidden' && Access::authorised($field)) { $classes = RegistryEditView::buildClasses($field); $attributes = ($classes ? ' class="' . htmlspecialchars($classes) . '"' : null) . ($field->attributes('width') || $field->attributes('align') ? ' style="' . ($field->attributes('width') ? 'width: ' . htmlspecialchars($field->attributes('width')) . ';' : null) . ($field->attributes('align') ? 'text-align: ' . htmlspecialchars($field->attributes('align')) . ';' : null) . '"' : null) . ($field->attributes('nowrap') ? ' nowrap="nowrap"' : null); $fieldName = $field->attributes('name'); $fieldOrdering = $field->attributes('allowordering'); $return .= '<th' . $attributes . '>'; if ($field->attributes('type') == 'primarycheckbox') { $jsToggleAll = "cbToggleAll( this, " . count($modelRows) . ", '" . $controllerView->fieldId('id') . "' );"; $return .= '<input type="checkbox" id="' . $controllerView->fieldId('toggle') . '" name="' . $controllerView->fieldName('toggle') . '" value="" onclick="' . $jsToggleAll . '" />'; } else { $fieldIcon = null; if ($fieldOrdering) { $fieldSort = explode(',', $fieldOrdering); $fieldAsc = in_array('ascending', $fieldSort); $fieldDesc = in_array('descending', $fieldSort); if ($fieldAsc && $this->orderby == $fieldName . '_asc') { // If ascending is allowed and is already active then set click to descending if descending is allowed: if ($fieldDesc) { $return .= '<a href="javascript: void(0);" class="text-nowrap cbTableBrowserSort cbTableBrowserSortDesc" data-table-sort="' . htmlspecialchars($fieldName . '_desc') . '">'; } else { $return .= '<a href="javascript: void(0);">'; } $fieldIcon = ' <span class="fa fa-sort-alpha-asc text-default"></span>'; } elseif ($fieldDesc && $this->orderby == $fieldName . '_desc') { // If descending is allowed and is already active then set click to ascending if ascending is allowed: if ($fieldAsc) { $return .= '<a href="javascript: void(0);" class="text-nowrap cbTableBrowserSort cbTableBrowserSortAsc" data-table-sort="' . htmlspecialchars($fieldName . '_asc') . '">'; } else { $return .= '<a href="javascript: void(0);">'; } $fieldIcon = ' <span class="fa fa-sort-alpha-desc text-default"></span>'; } elseif ($fieldSort[0] == 'ascending') { // Default to ascending if this field allows it: $return .= '<a href="javascript: void(0);" class="cbTableBrowserSort cbTableBrowserSortAsc" data-table-sort="' . htmlspecialchars($fieldName . '_asc') . '">'; } elseif ($fieldSort[0] == 'descending') { // Default to descending if this field allows it: $return .= '<a href="javascript: void(0);" class="cbTableBrowserSort cbTableBrowserSortDesc" data-table-sort="' . htmlspecialchars($fieldName . '_desc') . '">'; } else { $return .= '<a href="javascript: void(0);">'; } } $return .= $field->attributes('description') ? cbTooltip(2, CBTxt::Th($field->attributes('description')), null, null, null, CBTxt::Th($field->attributes('label')), null, 'data-hascbtooltip="true"') : CBTxt::Th($field->attributes('label')); if ($fieldOrdering) { $return .= $fieldIcon . '</a>'; } } if ($field->attributes('type') == 'ordering') { if (!$fieldOrdering || in_array($this->orderby, array($fieldName . '_asc', $fieldName . '_desc', $fieldName))) { if ($fieldOrdering) { $field->addAttribute('noordering', 'false'); } if (strpos($field->attributes('onclick'), 'number') !== false) { $jsOrderSave = "cbsaveorder( this, " . count($modelRows) . ", '" . $controllerView->fieldId('id', null, false) . "', '" . $controllerView->taskName(false) . "', '" . $controllerView->subtaskName(false) . "', '" . $controllerView->subtaskValue('saveorder/' . $field->attributes('name'), false) . "' );"; $return .= ' <a href="javascript: void(0);" onclick="' . $jsOrderSave . '">' . '<span class="fa fa-save fa-lg text-default" title="' . htmlspecialchars(CBTxt::T('Save Order')) . '"></span>' . '</a>'; } } else { if ($fieldOrdering) { $field->addAttribute('noordering', 'true'); } } } $return .= '</th>'; $columnCount++; } } $return .= '</tr>' . '</thead>' . '</tbody>'; $total = count($modelRows); $controllerView->pageNav->setRowsNumber($total); if ($total) { for ($i = 0; $i < $total; $i++) { $controllerView->pageNav->setRowIndex($i); $renderer->setModelOfDataRowsNumber($i); $row = $modelRows[$i]; $rowlink = $listFieldsRows->attributes('link'); if ($rowlink) { $hrefRowEdit = $controllerView->drawUrl($rowlink, $listFieldsRows, $row, $row->id, false); if ($hrefRowEdit) { if ($listFieldsRows->attributes('target') == '_blank') { $onclickJS = 'window.open(\'' . htmlspecialchars(cbUnHtmlspecialchars($hrefRowEdit)) . '\', \'cbinvoice\', \'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no\'); return false;'; } else { $onclickJS = "window.location='" . htmlspecialchars(cbUnHtmlspecialchars($hrefRowEdit)) . "'"; } $rowOnclickHtml = ' onclick="' . $onclickJS . '"'; } else { $rowOnclickHtml = null; } } else { $rowOnclickHtml = null; } $controllerView->setControl_name($this->name . '[rows][' . $i . ']'); $return .= '<tr class="cbTableBrowserRow"' . $rowOnclickHtml . '>' . $renderer->renderEditRowView($listFieldsRows, $row, $controllerView, $options, $viewType, 'td') . '</tr>'; } } $controllerView->setControl_name($this->name); $return .= '</tbody>'; if ($total && (!$listFieldsPager || $listFieldsPager && $listFieldsPager->attributes('type') != 'none')) { if ($listFieldsPager) { $showPageLinks = strpos($listFieldsPager->attributes('type'), 'nopagelinks') === false; $showLimitBox = strpos($listFieldsPager->attributes('type'), 'nolimitbox') === false; $showPagesCount = strpos($listFieldsPager->attributes('type'), 'nopagescount') === false; } else { $showPageLinks = true; $showLimitBox = true; $showPagesCount = true; } if ($controllerView->pageNav->total <= $controllerView->pageNav->limit) { $showPageLinks = false; } $return .= '<tfoot>' . '<tr class="cbTableBrowserRowsPaging">' . '<th colspan="' . (int) $columnCount . '" class="text-center">' . $controllerView->pageNav->getListFooter($showPageLinks, $showLimitBox, $showPagesCount) . '</th>' . '</tr>' . '</tfoot>' . '</table>'; } elseif ($controllerView->pageNav !== null) { $return .= '</table>' . $controllerView->pageNav->getLimitBox(false); } else { $return .= '</table>'; } } elseif ($controllerView->pageNav !== null) { $return .= $controllerView->pageNav->getLimitBox(false); } $return .= '<input type="hidden" name="' . $controllerView->fieldName('subtask') . '" value="" />'; $statistics = $controllerView->getStatistics(); if ($statistics) { foreach ($statistics as $stat) { $return .= $renderer->renderEditRowView($stat['view'], $stat['values'], $controllerView, $options, 'view', 'table'); } } $return .= '</div>'; echo $return; }
/** * Renders as ECHO HTML code * * @param SimpleXMLElement $modelView * @param array $modelRows * @param DrawController $controllerView * @param array $options * @return void */ protected function renderMenuGroup(&$modelView, &$modelRows, &$controllerView, $options) { global $_PLUGINS; $htmlFormatting = 'span'; if (count($this->_controllerModel->children()) > 0) { //TBD: not needed yet, but kept if needed $this->_applyStylingToMeAndChildren( $this->_controllerModel, $this->styling ); echo $this->renderMenuGroupHeader($this->_controllerModel, $htmlFormatting); foreach ($this->_controllerModel->children() as $child) { /** @var $child SimpleXMLElement */ // Check if ACL authorizes to view and to use that menu: if (!Access::authorised($child)) { continue; } if ($child->getName() == 'menu') { // Check if ACL authorizes to use the action linked by that menu: if (!$this->authorised($child)) { continue; } $menuName = $child->attributes('name'); echo $this->renderMenu($child, $modelRows[$menuName], $controllerView, $options, $htmlFormatting); } elseif ($child->getName() == 'showview') { $showviewType = $child->attributes('type'); if ($showviewType == 'plugins') { $groups = explode(',', $child->attributes('groups')); $action = $child->attributes('action'); $path = $child->attributes('path'); foreach ($groups as $group) { $matches = null; if (preg_match('/^([^\\[]+)\\[(.+)\\]$/', $group, $matches)) { $classId = $matches[2]; $group = $matches[1]; } else { $classId = null; } $_PLUGINS->loadPluginGroup($group, $classId, 0); $loadedPlugins = $_PLUGINS->getLoadedPluginGroup($group); foreach ($loadedPlugins as $plugin) { $element = $_PLUGINS->loadPluginXML('action', $action, $plugin->id); $viewModel = $element->getElementByPath($path); if ($viewModel) { foreach ($viewModel->children() as $extChild) { /** @var $extChild SimpleXMLElement */ if ($extChild->getName() == 'menu') { // Check if ACL authorizes to use the action linked by that menu: if (!$this->authorised($extChild)) { continue; } $menuName = $extChild->attributes('name'); echo $this->renderMenu($extChild, $modelRows[$menuName], $controllerView, $options, $htmlFormatting); } } } } } } elseif ($showviewType == 'xml') { // e.g.: <showview name="gateway_paymentstatus_information" mode="view" type="xml" file="processors/{payment_method}/edit.gateway" path="/*/views/view[@name="paymentstatusinformation"]" mandatory="false" /> $fromNode = $child->attributes('path'); $fromFile = $child->attributes('file'); $mandatory = $child->attributes('mandatory'); if ($fromNode && $fromFile !== null) { // $this->substituteName( $fromFile, true ); // $this->substituteName( $fromNode, false ); if ($fromFile !== '') { $fromFile = RegistryEditView::pathFromXML($fromFile . '.xml', $child, $this->_pluginObject); } if (strpos($fromFile, '/*/') !== false) { $parts = explode('/*/', $fromFile); $fromFiles = cbReadDirectory($parts[0], '.', false, true); // '^' . preg_quote( $subparts[0], '/' ) . '$' } else { $parts = null; $fromFiles = array($fromFile); } foreach ($fromFiles as $fromDirOrFile) { $viewModel = null; if ($fromDirOrFile === '') { $viewModel = $this->_views->xpath($fromNode); } else { if (!isset($parts) || is_dir($fromDirOrFile)) { $fromDirOrFile = $fromDirOrFile . (isset($parts[1]) ? '/' . $parts[1] : ''); if (file_exists($fromDirOrFile)) { $fromRoot = new SimpleXMLElement($fromDirOrFile, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0), true); $viewModel = $fromRoot->xpath($fromNode); } } else { continue; } } if ($viewModel && count($viewModel)) { foreach ($viewModel[0]->children() as $extChild) { /** @var $extChild SimpleXMLElement */ if ($extChild->getName() == 'menu') { // Check if ACL authorizes to use the action linked by that menu: if (!$this->authorised($extChild)) { continue; } $menuName = $extChild->attributes('name'); echo $this->renderMenu($extChild, $modelRows[$menuName], $controllerView, $options, $htmlFormatting); } } } elseif ($mandatory == 'false') { continue; } else { trigger_error('MenuController:showview: View file ' . $fromDirOrFile . ', path: ' . $fromNode . ' does not exist or is empty.', E_USER_NOTICE); } } } } } } echo $this->renderMenuGroupFooter($this->_controllerModel, $htmlFormatting); } }