/** * {@inheritdoc} */ public function handle(\Input $input) { $this->handleRunOnce(); // PATCH if ($input->post('FORM_SUBMIT') == 'database-update') { $count = 0; $sql = deserialize($input->post('sql')); if (is_array($sql)) { foreach ($sql as $key) { if (isset($_SESSION['sql_commands'][$key])) { $this->Database->query(str_replace('DEFAULT CHARSET=utf8;', 'DEFAULT CHARSET=utf8 COLLATE ' . $GLOBALS['TL_CONFIG']['dbCollation'] . ';', $_SESSION['sql_commands'][$key])); $count++; } } } $_SESSION['sql_commands'] = array(); Messages::addConfirmation(sprintf($GLOBALS['TL_LANG']['composer_client']['databaseUpdated'], $count)); $this->reload(); } /** @var \Contao\Database\Installer $installer */ $installer = \System::importStatic('Database\\Installer'); $form = $installer->generateSqlForm(); if (empty($form)) { Messages::addInfo($GLOBALS['TL_LANG']['composer_client']['databaseUptodate']); $this->redirect('contao/main.php?do=composer'); } $form = preg_replace('#(<label for="sql_\\d+")>(CREATE TABLE)#', '$1 class="create_table">$2', $form); $form = preg_replace('#(<label for="sql_\\d+")>(ALTER TABLE `[^`]+` ADD)#', '$1 class="alter_add">$2', $form); $form = preg_replace('#(<label for="sql_\\d+")>(ALTER TABLE `[^`]+` DROP)#', '$1 class="alter_drop">$2', $form); $form = preg_replace('#(<label for="sql_\\d+")>(DROP TABLE)#', '$1 class="drop_table">$2', $form); $template = new \BackendTemplate('be_composer_client_update'); $template->composer = $this->composer; $template->form = $form; return $template->parse(); }
protected function processForm() { // get a product collection (aka cart) global $objPage; $objCart = new Cart(); // Can't call the individual rows here, it would trigger markModified and a save() $objCart->setRow(array_merge($objCart->row(), array('tstamp' => time(), 'member' => 0, 'uniqid' => null, 'config_id' => $this->iso_config_id, 'store_id' => (int) \PageModel::findByPk($objPage->rootId)->iso_store_id))); $objSubmission = $this->getSubmission(false); // add products to cart foreach ($this->arrProducts as $arrProduct) { $strProduct = 'product_' . $arrProduct['product']->id; $strQuantity = 'quantity_' . $arrProduct['product']->id; if (($this->getProductCount() > 1 || $this->getTypeCount() > 1) && !$objSubmission->{$strProduct}) { continue; } if (!$objCart->addProduct($arrProduct['product'], $arrProduct['useQuantity'] ? $objSubmission->{$strQuantity} : 1)) { $this->transformIsotopeErrorMessages(); return; } } $objCart->save(); $objOrder = $objCart->getDraftOrder(); // temporarily override the cart for generating the reviews... $objCartTmp = Isotope::getCart(); Isotope::setCart($objCart); // create steps $arrSteps = array(); $arrCheckoutInfo = array(); // billing address $objBillingAddress = new Address(); foreach ($this->arrBillingAddressFields as $strName) { $objBillingAddress->{$strName} = $objSubmission->{$strName}; } $objBillingAddress->save(); $objOrder->setBillingAddress($objBillingAddress); $objBillingAddressStep = new BillingAddress($this->objCheckoutModule); $arrSteps[] = $objBillingAddressStep; $arrCheckoutInfo['billing_address'] = $objBillingAddressStep->review()['billing_address']; // shipping address $objShippingAddress = new Address(); // standard isotope handling for distinguishing between the address types: // -> if only a billing address is available, it's also the shipping address foreach ($objSubmission->shippingaddress ? $this->arrShippingAddressFields : $this->arrBillingAddressFields as $strName) { $objShippingAddress->{str_replace('shippingaddress_', '', $strName)} = $objSubmission->{$objSubmission->shippingaddress ? $strName : str_replace('shippingaddress_', 'billingaddress_', $strName)}; } $objShippingAddress->save(); // $objOrder->setShippingAddress($objShippingAddress); // $objShippingAddressStep = new ShippingAddress($this->objCheckoutModule); // $arrSteps[] = $objShippingAddressStep; // $arrCheckoutInfo['shipping_address'] = $objShippingAddressStep->review()['shipping_address']; // add shipping method $objIsotopeShipping = Flat::findByPk($this->iso_shipping_modules); $objOrder->setShippingMethod($objIsotopeShipping); $objShippingMethodStep = new ShippingMethod($this->objCheckoutModule); $arrSteps[] = $objShippingMethodStep; $arrCheckoutInfo['shipping_method'] = $objShippingMethodStep->review()['shipping_method']; // add all the checkout info to the order $objOrder->checkout_info = $arrCheckoutInfo; $objOrder->notes = $objSubmission->notes; //... restore the former cart again Isotope::setCart($objCartTmp); $objOrder->nc_notification = $this->nc_notification; $objOrder->email_data = $this->getNotificationTokensFromSteps($arrSteps, $objOrder); // !HOOK: pre-process checkout if (isset($GLOBALS['ISO_HOOKS']['preCheckout']) && is_array($GLOBALS['ISO_HOOKS']['preCheckout'])) { foreach ($GLOBALS['ISO_HOOKS']['preCheckout'] as $callback) { $objCallback = \System::importStatic($callback[0]); if ($objCallback->{$callback}[1]($objOrder, $this->objCheckoutModule) === false) { \System::log('Callback ' . $callback[0] . '::' . $callback[1] . '() cancelled checkout for Order ID ' . $this->id, __METHOD__, TL_ERROR); $this->objCheckoutModule->redirectToStep('failed'); } } } $objOrder->lock(); $objOrder->checkout(); $objOrder->complete(); if (is_array($this->dca['config']['onsubmit_callback'])) { foreach ($this->dca['config']['onsubmit_callback'] as $key => $callback) { if ($callback[0] == 'Isotope\\Backend\\ProductCollection\\Callback' && $callback[1] == 'executeSaveHook') { unset($this->dca['config']['onsubmit_callback'][$key]); break; } } } $this->transformIsotopeErrorMessages(); parent::processForm(); }
/** * Check if collection item is available * * @return bool */ public function isAvailable() { if ($this->isLocked()) { return true; } if (isset($GLOBALS['ISO_HOOKS']['itemIsAvailable']) && is_array($GLOBALS['ISO_HOOKS']['itemIsAvailable'])) { foreach ($GLOBALS['ISO_HOOKS']['itemIsAvailable'] as $callback) { $objCallback = \System::importStatic($callback[0]); $available = $objCallback->{$callback}[1]($this); // If return value is boolean then we accept it as result if (true === $available || false === $available) { return $available; } } } if (!$this->hasProduct() || !$this->getProduct()->isAvailableForCollection($this->getRelated('pid'))) { return false; } // @todo change to ->getConfiguration() in Isotope 3.0 $arrConfig = $this->getOptions(); foreach ($this->getProduct()->getOptions() as $k => $v) { if ($arrConfig[$k] !== $v) { return false; } } return true; }
protected function compile() { $arrProducts = $this->findProducts(); // No products found if (!is_array($arrProducts) || empty($arrProducts)) { // Do not index or cache the page $objPage->noSearch = 1; $objPage->cache = 0; $this->Template->empty = true; $this->Template->type = 'empty'; $this->Template->message = $GLOBALS['TL_LANG']['MSC']['noProducts']; $this->Template->products = array(); return; } $arrBuffer = array(); foreach ($arrProducts as $objProduct) { $arrConfig = array('module' => $this, 'template' => $this->iso_list_layout ?: $objProduct->getRelated('type')->list_template, 'gallery' => $this->iso_gallery ?: $objProduct->getRelated('type')->list_gallery, 'buttons' => deserialize($this->iso_buttons, true), 'useQuantity' => $this->iso_use_quantity, 'jumpTo' => $this->findJumpToPage($objProduct)); if (\Environment::get('isAjaxRequest') && \Input::post('AJAX_MODULE') == $this->id && \Input::post('AJAX_PRODUCT') == $objProduct->getProductId()) { $objResponse = new HtmlResponse($objProduct->generate($arrConfig)); $objResponse->send(); } $arrCSS = deserialize($objProduct->cssID, true); $arrBuffer[] = array('cssID' => $arrCSS[0] != '' ? ' id="' . $arrCSS[0] . '"' : '', 'class' => trim('product ' . ($objProduct->isNew() ? 'new ' : '') . $arrCSS[1]), 'html' => $objProduct->generate($arrConfig), 'product' => $objProduct); } // HOOK: to add any product field or attribute to mod_iso_productlist template if (isset($GLOBALS['ISO_HOOKS']['generateProductList']) && is_array($GLOBALS['ISO_HOOKS']['generateProductList'])) { foreach ($GLOBALS['ISO_HOOKS']['generateProductList'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrBuffer = $objCallback->{$callback}[1]($arrBuffer, $arrProducts, $this->Template, $this); } } RowClass::withKey('class')->addCount('product_')->addEvenOdd('product_')->addFirstLast('product_')->addGridRows($this->iso_cols)->addGridCols($this->iso_cols)->applyTo($arrBuffer); $this->Template->products = $arrBuffer; }
/** * Initialize the backend view. * * @param DataContainer $dataContainer The data container. * * @return void */ public function initialize($dataContainer) { if (TL_MODE !== 'BE') { return; } $this->getServiceContainer()->getAssetsManager()->addStylesheet('system/modules/content-node/assets/css/backend.css'); $callback = $this->definition->get('list/sorting/child_record_callback'); if (is_array($callback)) { $callback[0] = \System::importStatic($callback[0]); } $renderer = new BackendRenderer($this->registry, $callback); $definition = $this->getServiceContainer()->getDcaManager()->get('tl_content'); $definition->set('list/sorting/child_record_callback', $renderer); $parentType = null; if ($dataContainer->parentTable === 'tl_content_node') { $parent = \ContentModel::findByPk(CURRENT_ID); if ($parent && $this->registry->hasNodeType($parent->tye)) { $parentType = $this->registry->getNode($parent->type); } } try { $restriction = new ContentElementAccess($this->definition, $this->registry, $this->getServiceContainer()->getDatabaseConnection(), $this->getServiceContainer()->getSession(), $this->getServiceContainer()->getInput()); $restriction->restrict($dataContainer->id, $parentType); } catch (AccessDeniedException $e) { \Controller::log($e->getMessage(), 'ContentElementAccess::resitrct', TL_ACCESS); \Controller::redirect(\Environment::get('script') . '?act=error'); } }
public function getActiveLayoutSections(\DataContainer $dc) { $callback = $GLOBALS['TL_DCA']['tl_article']['fields']['inColumn']['bit3_merger_original_options_callback']; if (is_array($callback)) { $object = \System::importStatic($callback[0]); $methodName = $callback[1]; $sections = $object->{$methodName}($dc); } else { $sections = call_user_func($callback, $dc); } if ($dc->activeRecord->pid) { $page = \PageModel::findWithDetails($dc->activeRecord->pid); // Get the layout sections foreach (array('layout', 'mobileLayout') as $key) { if (!$page->{$key}) { continue; } $layout = \LayoutModel::findByPk($page->{$key}); if ($layout === null) { continue; } $modules = deserialize($layout->modules); if (empty($modules) || !is_array($modules)) { continue; } // Find all sections with an article module (see #6094) foreach ($modules as $module) { if ($module['mod'] != 0 && $module['enable']) { $this->joinModule($module['col'], $module['mod'], $sections); } } } } return array_values(array_unique($sections)); }
/** * Handle the callback. * * @param array|callable $callback Callback as Contao array notation or as PHP callable. * @param array $arguments List of arguments being passed to the callback. * * @return mixed * @throws InvalidArgumentException On callback is not callable. */ public function invoke($callback, array $arguments = []) { if (is_array($callback)) { $callback[0] = \System::importStatic($callback[0]); } Assert::isCallable($callback); return call_user_func_array($callback, $arguments); }
/** * Call the button callback. * * @param array $button The button definition. * @param array $row The current row. * @param string $label The label. * @param string $title The title. * @param string $attributes The attributes. * * @return string */ private function callButtonCallback($button, $row, $label, $title, $attributes) { if (is_array($button['button_callback'])) { $button['button_callback'][0] = \System::importStatic($button['button_callback'][0]); } if (is_callable($button['button_callback'])) { return call_user_func($button['button_callback'], $row, $button['href'] .= '&nodes=1', $label, $title, $button['icon'], $attributes, $this->definition->getName(), array(), null, false, null, null); } return ''; }
/** * Generate item label and return it as HTML string * @param object * @param string * @param object * @param string * @param mixed * @return string */ public static function generateItemLabel($objItem, $strForeignTable, $objDca = null, $strTitleField = '', $varCallback = null) { $args = array(); $label = ''; $blnSimple = false; $showFields = $GLOBALS['TL_DCA'][$strForeignTable]['list']['label']['fields']; // Generate simple label, e.g. for breadcrumb if ($strTitleField != '') { $blnSimple = true; $showFields['titleField'] = $strTitleField; } foreach ($showFields as $k => $v) { // Decrypt the value if ($GLOBALS['TL_DCA'][$strForeignTable]['fields'][$v]['eval']['encrypt']) { $objItem->{$v} = \Encryption::decrypt(deserialize($objItem->{$v})); } if (strpos($v, ':') !== false) { list($strKey, $strTable) = explode(':', $v); list($strTable, $strField) = explode('.', $strTable); $objRef = \Database::getInstance()->prepare("SELECT " . $strField . " FROM " . $strTable . " WHERE id=?")->limit(1)->execute($objItem->{$strKey}); $args[$k] = $objRef->numRows ? $objRef->{$strField} : ''; } elseif (in_array($GLOBALS['TL_DCA'][$strForeignTable]['fields'][$v]['flag'], array(5, 6, 7, 8, 9, 10))) { $args[$k] = \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], $objItem->{$v}); } elseif ($GLOBALS['TL_DCA'][$strForeignTable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$strForeignTable]['fields'][$v]['eval']['multiple']) { $args[$k] = $objItem->{$v} != '' ? isset($GLOBALS['TL_DCA'][$strForeignTable]['fields'][$v]['label'][0]) ? $GLOBALS['TL_DCA'][$strForeignTable]['fields'][$v]['label'][0] : $v : ''; } else { $args[$k] = $GLOBALS['TL_DCA'][$strForeignTable]['fields'][$v]['reference'][$objItem->{$v}] ?: $objItem->{$v}; } } $label = vsprintf(strlen($GLOBALS['TL_DCA'][$strForeignTable]['list']['label']['format']) ? $GLOBALS['TL_DCA'][$strForeignTable]['list']['label']['format'] : '%s', $args); // Shorten the label if it is too long if ($GLOBALS['TL_DCA'][$strForeignTable]['list']['label']['maxCharacters'] > 0 && $GLOBALS['TL_DCA'][$strForeignTable]['list']['label']['maxCharacters'] < utf8_strlen(strip_tags($label))) { $label = trim(\String::substrHtml($label, $GLOBALS['TL_DCA'][$strForeignTable]['list']['label']['maxCharacters'])) . ' …'; } $label = preg_replace('/\\(\\) ?|\\[\\] ?|\\{\\} ?|<> ?/', '', $label); // Use the default callback if none provided if ($varCallback === null) { $varCallback = $GLOBALS['TL_DCA'][$strForeignTable]['list']['label']['label_callback']; } // Call the label_callback ($row, $label, $this) if (is_array($varCallback)) { $strClass = $varCallback[0]; $strMethod = $varCallback[1]; $label = \System::importStatic($strClass)->{$strMethod}($objItem->row(), $label, $objDca, '', $blnSimple, false); } elseif (is_callable($varCallback)) { $label = $varCallback($objItem->row(), $label, $objDca, '', $blnSimple, false); } else { $label = \Image::getHtml('iconPLAIN.gif') . ' ' . ($blnSimple ? $args['titleField'] : $label); } return $label; }
/** * Must be defined cause parent is protected. * * @access public * @return void */ public function __construct() { parent::__construct(); // Contao Hooks are not save to be run on the postsale script (e.g. parseFrontendTemplate) unset($GLOBALS['TL_HOOKS']); // Need to load our own Hooks (e.g. loadDataContainer) include TL_ROOT . '/system/modules/isotope/config/hooks.php'; // Default parameters $this->setModule(strlen(\Input::post('mod')) ? \Input::post('mod') : \Input::get('mod')); $this->setModuleId(strlen(\Input::post('id')) ? \Input::post('id') : \Input::get('id')); // HOOK: allow to add custom hooks for postsale script if (isset($GLOBALS['ISO_HOOKS']['initializePostsale']) && is_array($GLOBALS['ISO_HOOKS']['initializePostsale'])) { foreach ($GLOBALS['ISO_HOOKS']['initializePostsale'] as $callback) { $objCallback = \System::importStatic($callback[0]); $objCallback->{$callback}[1]($this); } } }
/** * Send data submissions to Salesforce * * Class: Form * Method: processFormData * Hook: $GLOBALS['TL_HOOKS']['processFormData'] * * @access public * @param array * @param array * @param array * @param array * @return void */ public function run($arrSubmitted, $arrFormData, $arrFiles, $arrLabels, $objForm) { try { if ($objForm->useSalesforce && $objForm->salesforceAPIConfig && $objForm->salesforceSObject) { if ($this->connectToSalesforce($objForm->salesforceAPIConfig)) { $arrSObjectConfig = $GLOBALS['TL_SOBJECTS'][$objForm->salesforceSObject]; if (is_array($arrSObjectConfig) && count($arrSObjectConfig) && $arrSObjectConfig['class'] && class_exists($arrSObjectConfig['class'])) { $strMethod = 'create'; // Todo: Maybe we make this an option? create, update, etc. $strClass = $arrSObjectConfig['class']; $arrData = static::getSalesforceFields($arrSubmitted, $objForm->id); // todo: check mandatory fields for different object types // !HOOK: alter Salesforce data before sending if (isset($GLOBALS['TL_HOOKS']['preSendSalesforceData']) && is_array($GLOBALS['TL_HOOKS']['preSendSalesforceData'])) { foreach ($GLOBALS['TL_HOOKS']['preSendSalesforceData'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrData = $objCallback->{$callback}[1]($strClass, $arrData, $arrSubmitted, $arrFormData, $arrFiles, $arrLabels, $objForm, $this->objClient, $strMethod); } } // Create the Salesforce object $objSObject = new $strClass($arrData); // Send the data to Salesforce $response = $this->objClient->{$strMethod}(array($objSObject), $strClass::getType()); // !HOOK: execute custom actions after sending data to Salesforce if (isset($GLOBALS['TL_HOOKS']['postSendSalesforceData']) && is_array($GLOBALS['TL_HOOKS']['postSendSalesforceData'])) { foreach ($GLOBALS['TL_HOOKS']['postSendSalesforceData'] as $callback) { $objCallback = \System::importStatic($callback[0]); $objCallback->{$callback}[1]($response, $objSObject, $arrData, $arrSubmitted, $arrFormData, $arrFiles, $arrLabels, $objForm, $this->objClient, $strMethod); } } if ($response[0]->isSuccess()) { \System::log('Salesforce ' . $objForm->salesforceSObject . ' (ID ' . $response[0]->getId() . ') successful.', __METHOD__, TL_FORMS); } else { $errors = $response[0]->getErrors(); \System::log('Salesforce object creation failed: ' . $errors[0]->getMessage(), __METHOD__, TL_ERROR); } } } } } catch (\Exception $e) { \System::log('Failed to send data to Salesforce: ' . $e->getMessage(), __METHOD__, TL_ERROR); } return false; }
/** * Publish/unpublish rule * @param integer * @param boolean * @param \DataContainer */ public function toggleVisibility($intId, $blnVisible, \DataContainer $dc = null) { $objVersions = new \Versions('tl_css_class_replacer', $intId); $objVersions->initialize(); // Trigger the save_callback if (is_array($GLOBALS['TL_DCA']['tl_css_class_replacer']['fields']['published']['save_callback'])) { foreach ($GLOBALS['TL_DCA']['tl_css_class_replacer']['fields']['published']['save_callback'] as $callback) { if (is_array($callback)) { $blnVisible = \System::importStatic($callback[0])->{$callback}[1]($blnVisible, $dc ?: $this); } elseif (is_callable($callback)) { $blnVisible = $callback($blnVisible, $dc ?: $this); } } } // Update the database \Database::getInstance()->prepare("UPDATE tl_css_class_replacer SET tstamp=" . time() . ", published='" . ($blnVisible ? 1 : '') . "' WHERE id=?")->execute($intId); $objVersions->create(); \System::log('A new version of record "tl_css_class_replacer.id=' . $intId . '" has been created', __METHOD__, TL_GENERAL); }
/** * Send this message using its gateway * @param array * @param string * @return bool */ public function send(array $arrTokens, $strLanguage = '') { /** @var Gateway $objGatewayModel */ if (($objGatewayModel = $this->getRelated('gateway')) === null) { \System::log(sprintf('Could not find gateway ID "%s".', $this->gateway), __METHOD__, TL_ERROR); return false; } if (null === $objGatewayModel->getGateway()) { \System::log(sprintf('Could not find gateway class for gateway ID "%s".', $objGatewayModel->id), __METHOD__, TL_ERROR); return false; } if (isset($GLOBALS['TL_HOOKS']['sendNotificationMessage']) && is_array($GLOBALS['TL_HOOKS']['sendNotificationMessage'])) { foreach ($GLOBALS['TL_HOOKS']['sendNotificationMessage'] as $arrCallback) { $blnSuccess = \System::importStatic($arrCallback[0])->{$arrCallback}[1]($this, $arrTokens, $strLanguage, $objGatewayModel); if (!$blnSuccess) { return false; } } } return $objGatewayModel->getGateway()->send($this, $arrTokens, $strLanguage); }
protected function buildCache(\TwigBackendTemplate $template, Cache $cache, \Session $session) { // clear the existing caches /** @var \Automator $automator */ $automator = \System::importStatic('Automator'); $automator->purgeScriptCache(); if ($cache instanceof CacheProvider) { $cache->deleteAll(); } // overwrite frontend username $template->frontendUsername = \Input::post('user'); $session->set(self::SESSION_LAST_USERNAME, $template->frontendUsername); // Use searchable pages to generate assets // TODO this seems to be not a good idea... // $GLOBALS['TL_CONFIG']['indexProtected'] = true; // $template->urls = \Backend::findSearchablePages(0, '', true); list($guestUrls, $memberUrls) = $this->buildPageUrls(0, \Environment::get('base') . '/'); $template->guestUrls = $guestUrls; $template->memberUrls = $memberUrls; $cache->save(ThemePlus::CACHE_CREATION_TIME, time()); }
/** * Generate array representation for download * * @param bool $blnOrderPaid * * @return array */ public function getForTemplate($blnOrderPaid = false) { global $objPage; $objDownload = $this->getRelated('download_id'); if (null === $objDownload) { return array(); } $arrDownloads = array(); $allowedDownload = trimsplit(',', strtolower($GLOBALS['TL_CONFIG']['allowedDownload'])); foreach ($objDownload->getFiles() as $objFileModel) { $objFile = new \File($objFileModel->path, true); if (!in_array($objFile->extension, $allowedDownload) || preg_match('/^meta(_[a-z]{2})?\\.txt$/', $objFile->basename)) { continue; } // Send file to the browser if ($blnOrderPaid && $this->canDownload() && \Input::get('download') == $objDownload->id && \Input::get('file') == $objFileModel->path) { $path = $objFileModel->path; if (isset($GLOBALS['ISO_HOOKS']['downloadFromProductCollection']) && is_array($GLOBALS['ISO_HOOKS']['downloadFromProductCollection'])) { foreach ($GLOBALS['ISO_HOOKS']['downloadFromProductCollection'] as $callback) { $objCallback = \System::importStatic($callback[0]); $path = $objCallback->{$callback}[1]($path, $objFileModel, $objDownload, $this); } } $this->download($objFileModel->path); } $arrMeta = \Frontend::getMetaData($objFileModel->meta, $objPage->language); // Use the file name as title if none is given if ($arrMeta['title'] == '') { $arrMeta['title'] = specialchars(str_replace('_', ' ', preg_replace('/^[0-9]+_/', '', $objFile->filename))); } $strHref = ''; if (TL_MODE == 'FE') { $strHref = \Haste\Util\Url::addQueryString('download=' . $objDownload->id . '&file=' . $objFileModel->path); } // Add the image $arrDownloads[] = array('id' => $this->id, 'name' => $objFile->basename, 'title' => $arrMeta['title'], 'link' => $arrMeta['title'], 'caption' => $arrMeta['caption'], 'href' => $strHref, 'filesize' => \System::getReadableSize($objFile->filesize, 1), 'icon' => TL_ASSETS_URL . 'assets/contao/images/' . $objFile->icon, 'mime' => $objFile->mime, 'meta' => $arrMeta, 'extension' => $objFile->extension, 'path' => $objFile->dirname, 'remaining' => $objDownload->downloads_allowed > 0 ? sprintf($GLOBALS['TL_LANG']['MSC']['downloadsRemaining'], intval($this->downloads_remaining)) : '', 'downloadable' => $blnOrderPaid && $this->canDownload()); } return $arrDownloads; }
/** * Get the filename from a database config. * * @param \Database\Result $config * @return string */ public static function getName($config) { if ($config->filename == '') { $filename = 'export_' . md5(uniqid()); if ($config->type) { $filename .= '.' . $config->type; } return $filename; } $tokens = array('time' => \Date::parse($GLOBALS['TL_CONFIG']['timeFormat']), 'date' => \Date::parse($GLOBALS['TL_CONFIG']['dateFormat']), 'datim' => \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'])); // Add custom logic if (isset($GLOBALS['TL_HOOKS']['getLeadsFilenameTokens']) && is_array($GLOBALS['TL_HOOKS']['getLeadsFilenameTokens'])) { foreach ($GLOBALS['TL_HOOKS']['getLeadsFilenameTokens'] as $callback) { if (is_array($callback)) { $tokens = \System::importStatic($callback[0])->{$callback[1]}($tokens, $config); } elseif (is_callable($callback)) { $tokens = $callback($tokens, $config); } } } return \String::parseSimpleTokens($config->filename, $tokens); }
/** * Add this filter to the module's template or get the URL params * @param array * @param Contao\Template * @param Contao\Module * @param boolean * @return mixed string|bool|void */ public static function generateFilter(&$arrCategories, &$objTemplate, $objModule, $blnGenURL = false) { $arrRanges = static::getPriceRanges(); // !HOOK: custom price ranges if (isset($GLOBALS['ISO_HOOKS']['getFilterPriceRanges']) && is_array($GLOBALS['ISO_HOOKS']['getFilterPriceRanges'])) { foreach ($GLOBALS['ISO_HOOKS']['getFilterPriceRanges'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrRanges = $objCallback->{$callback}[1]($arrRanges, $arrCategories, $objTemplate, $objModule, $blnGenURL); } } if ($blnGenURL) { $arrPosted = (array) \Input::post(static::$strKey); //return the URL fragment needed for this filter to pass to the lister if (!empty($arrPosted)) { $arrURLFilters = array(); foreach ($arrPosted as $post) { //Check that they exist if (strlen(trim($post)) && (in_array($post, array_keys($arrRanges)) || in_array(htmlentities($post), array_keys($arrRanges)))) { $arrURLFilters[] = $post; } } if (count($arrURLFilters) > 0) { return static::$strKey . '/' . urlencode(Filter::cleanChars(implode(',', $arrURLFilters))); } } return false; } if (count($arrRanges) > 0) { $arrChecked = \Input::get(static::$strKey) ? explode(',', \Input::get(static::$strKey)) : array(); $objTemplate->hasPriceFilter = true; $objTemplate->price = array_map('htmlentities', $arrRanges); $objTemplate->priceselected = array_map('htmlentities', array_map(array('IsotopeDirect\\Filter\\Filter', 'uncleanChars'), $arrChecked)); $objTemplate->ppriceLabel = $GLOBALS['TL_LANG']['MSC'][static::$strKey . 'FilterLabel']; $objTemplate->priceBlankLabel = $GLOBALS['TL_LANG']['MSC']['directBlankOptionLabel']; } }
/** * Returns the prepared row according to the Row instance configuration. * * @param array $data * * @return array */ public function compile(array $data) { $compiled = array(); foreach ($this->columnConfig as $columnConfig) { // Add custom logic if (isset($GLOBALS['TL_HOOKS']['getLeadsExportRow']) && is_array($GLOBALS['TL_HOOKS']['getLeadsExportRow'])) { $value = null; foreach ($GLOBALS['TL_HOOKS']['getLeadsExportRow'] as $callback) { if (is_array($callback)) { $value = \System::importStatic($callback[0])->{$callback[1]}($columnConfig, $data, $this->config, $value); } elseif (is_callable($callback)) { $value = $callback($columnConfig, $data, $this->config, $value); } } // Store the value if ($value !== null) { $compiled[] = $value; continue; } } // Regular form field if (isset($columnConfig['id'])) { $value = $data[$columnConfig['id']]['value']; $label = $columnConfig['label']; } else { // Internal field $row = current($data); $value = $row[$columnConfig['valueColRef']]; $label = $row[$columnConfig['labelColRef']]; } $value = static::transformValue($value, $columnConfig); $label = static::prepareLabel($label); $compiled[] = static::getValueForOutput($columnConfig['value'], $value, $label); } return $compiled; }
/** * Get the sorting labels (asc/desc) for an attribute * @param string * @return array */ protected static function getSortingLabels($field) { $arrData = $GLOBALS['TL_DCA'][Product::getTable()]['fields'][$field]; switch ($arrData['eval']['rgxp']) { case 'price': case 'digit': return array($GLOBALS['TL_LANG']['MSC']['low_to_high'], $GLOBALS['TL_LANG']['MSC']['high_to_low']); case 'date': case 'time': case 'datim': return array($GLOBALS['TL_LANG']['MSC']['old_to_new'], $GLOBALS['TL_LANG']['MSC']['new_to_old']); } // !HOOK: custom sorting labels if (isset($GLOBALS['ISO_HOOKS']['sortingLabels']) && is_array($GLOBALS['ISO_HOOKS']['sortingLabels'])) { foreach ($GLOBALS['ISO_HOOKS']['sortingLabels'] as $callback) { $objCallback = \System::importStatic($callback[0]); $varReturn = $objCallback->{$callback}[1]($field, $arrData, null); if ($varReturn !== false) { return $varReturn; } } } return array($GLOBALS['TL_LANG']['MSC']['a_to_z'], $GLOBALS['TL_LANG']['MSC']['z_to_a']); }
/** * Resize the image * * @return $this The image object */ public function executeResize() { // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['executeResize']) && is_array($GLOBALS['TL_HOOKS']['executeResize'])) { foreach ($GLOBALS['TL_HOOKS']['executeResize'] as $callback) { $return = \System::importStatic($callback[0])->{$callback}[1]($this); if (is_string($return)) { $this->resizedPath = \System::urlEncode($return); return $this; } } } $importantPart = $this->getImportantPart(); $widthMatches = $this->fileObj->width == $this->getTargetWidth() || !$this->getTargetWidth(); $heightMatches = $this->fileObj->height == $this->getTargetHeight() || !$this->getTargetHeight(); $zoomMatches = $importantPart['x'] === 0 && $importantPart['y'] === 0 && $importantPart['width'] === $this->fileObj->width && $importantPart['height'] === $this->fileObj->height || !$this->getZoomLevel(); // No resizing required if ($widthMatches && $heightMatches && $zoomMatches) { // Return the target image (thanks to Tristan Lins) (see #4166) if ($this->getTargetPath()) { // Copy the source image if the target image does not exist or is older than the source image if (!file_exists(TL_ROOT . '/' . $this->getTargetPath()) || $this->fileObj->mtime > filemtime(TL_ROOT . '/' . $this->getTargetPath())) { \Files::getInstance()->copy($this->getOriginalPath(), $this->getTargetPath()); } $this->resizedPath = \System::urlEncode($this->getTargetPath()); return $this; } $this->resizedPath = \System::urlEncode($this->getOriginalPath()); return $this; } // Check whether the image exists already if (!\Config::get('debugMode')) { // Custom target (thanks to Tristan Lins) (see #4166) if ($this->getTargetPath() && !$this->getForceOverride()) { if (file_exists(TL_ROOT . '/' . $this->getTargetPath()) && $this->fileObj->mtime <= filemtime(TL_ROOT . '/' . $this->getTargetPath())) { $this->resizedPath = \System::urlEncode($this->getOriginalPath()); return $this; } } // Regular cache file if (file_exists(TL_ROOT . '/' . $this->getCacheName())) { // Copy the cached file if it exists if ($this->getTargetPath()) { \Files::getInstance()->copy($this->getCacheName(), $this->getTargetPath()); $this->resizedPath = \System::urlEncode($this->getTargetPath()); return $this; } $this->resizedPath = \System::urlEncode($this->getCacheName()); return $this; } } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['getImage']) && is_array($GLOBALS['TL_HOOKS']['getImage'])) { foreach ($GLOBALS['TL_HOOKS']['getImage'] as $callback) { $return = \System::importStatic($callback[0])->{$callback}[1]($this->getOriginalPath(), $this->getTargetWidth(), $this->getTargetHeight(), $this->getResizeMode(), $this->getCacheName(), $this->fileObj, $this->getTargetPath(), $this); if (is_string($return)) { $this->resizedPath = \System::urlEncode($return); return $this; } } } $svgNotPossible = $this->fileObj->isSvgImage && !extension_loaded('dom'); $gdNotPossible = $this->fileObj->isGdImage && (!extension_loaded('gd') || $this->fileObj->width > \Config::get('gdMaxImgWidth') || $this->fileObj->height > \Config::get('gdMaxImgHeight') || $this->getTargetWidth() > \Config::get('gdMaxImgWidth') || $this->getTargetHeight() > \Config::get('gdMaxImgHeight')); // Return the path to the original image if it cannot be handled if (!$this->fileObj->isImage || $svgNotPossible || $gdNotPossible) { $this->resizedPath = \System::urlEncode($this->getOriginalPath()); return $this; } // Create the resized image if ($this->fileObj->isSvgImage) { $this->executeResizeSvg(); } else { $this->executeResizeGd(); } // Resize the original image if ($this->getTargetPath()) { \Files::getInstance()->copy($this->getCacheName(), $this->getTargetPath()); $this->resizedPath = \System::urlEncode($this->getTargetPath()); return $this; } $this->resizedPath = \System::urlEncode($this->getCacheName()); return $this; }
/** * Add the file meta information to the request * * @param string $strUuid * @param string $strPtable * @param integer $intPid */ public static function addFileMetaInformationToRequest($strUuid, $strPtable, $intPid) { $objFile = \FilesModel::findByUuid($strUuid); if ($objFile === null) { return; } $arrMeta = deserialize($objFile->meta); if (empty($arrMeta)) { return; } $objPage = null; $db = \Database::getInstance(); switch ($strPtable) { case 'tl_article': $objPage = $db->prepare("SELECT * FROM tl_page WHERE id=(SELECT pid FROM tl_article WHERE id=?)")->execute($intPid); break; case 'tl_news': $objPage = $db->prepare("SELECT * FROM tl_page WHERE id=(SELECT jumpTo FROM tl_news_archive WHERE id=(SELECT pid FROM tl_news WHERE id=?))")->execute($intPid); break; case 'tl_news_archive': $objPage = $db->prepare("SELECT * FROM tl_page WHERE id=(SELECT jumpTo FROM tl_news_archive WHERE id=?)")->execute($intPid); break; case 'tl_calendar_events': $objPage = $db->prepare("SELECT * FROM tl_page WHERE id=(SELECT jumpTo FROM tl_calendar WHERE id=(SELECT pid FROM tl_calendar_events WHERE id=?))")->execute($intPid); break; case 'tl_calendar': $objPage = $db->prepare("SELECT * FROM tl_page WHERE id=(SELECT jumpTo FROM tl_calendar WHERE id=?)")->execute($intPid); break; case 'tl_faq_category': $objPage = $db->prepare("SELECT * FROM tl_page WHERE id=(SELECT jumpTo FROM tl_faq_category WHERE id=?)")->execute($intPid); break; default: // HOOK: support custom modules if (isset($GLOBALS['TL_HOOKS']['addFileMetaInformationToRequest']) && is_array($GLOBALS['TL_HOOKS']['addFileMetaInformationToRequest'])) { foreach ($GLOBALS['TL_HOOKS']['addFileMetaInformationToRequest'] as $callback) { if (($val = \System::importStatic($callback[0])->{$callback[1]}($strPtable, $intPid)) !== false) { $objPage = $val; } } } break; } if ($objPage === null || $objPage->numRows < 1) { return; } $objModel = new \PageModel(); $objModel->setRow($objPage->row()); $objModel->loadDetails(); // Convert the language to a locale (see #5678) $strLanguage = str_replace('-', '_', $objModel->rootLanguage); if (isset($arrMeta[$strLanguage])) { if (\Input::post('alt') == '' && !empty($arrMeta[$strLanguage]['title'])) { \Input::setPost('alt', $arrMeta[$strLanguage]['title']); } if (\Input::post('caption') == '' && !empty($arrMeta[$strLanguage]['caption'])) { \Input::setPost('caption', $arrMeta[$strLanguage]['caption']); } } }
/** * Resize an image and store the resized version in the assets/images folder * * @param string $image The image path * @param integer $width The target width * @param integer $height The target height * @param string $mode The resize mode * @param string $target An optional target path * @param boolean $force Override existing target images * * @return string|null The path of the resized image or null */ public static function get($image, $width, $height, $mode = '', $target = null, $force = false) { if ($image == '') { return null; } $image = rawurldecode($image); // Check whether the file exists if (!is_file(TL_ROOT . '/' . $image)) { \System::log('Image "' . $image . '" could not be found', __METHOD__, TL_ERROR); return null; } $objFile = new \File($image, true); $arrAllowedTypes = trimsplit(',', strtolower(\Config::get('validImageTypes'))); // Check the file type if (!in_array($objFile->extension, $arrAllowedTypes)) { \System::log('Image type "' . $objFile->extension . '" was not allowed to be processed', __METHOD__, TL_ERROR); return null; } // No resizing required if (($objFile->width == $width || !$width) && ($objFile->height == $height || !$height)) { // Return the target image (thanks to Tristan Lins) (see #4166) if ($target) { // Copy the source image if the target image does not exist or is older than the source image if (!file_exists(TL_ROOT . '/' . $target) || $objFile->mtime > filemtime(TL_ROOT . '/' . $target)) { \Files::getInstance()->copy($image, $target); } return \System::urlEncode($target); } return \System::urlEncode($image); } // No mode given if ($mode == '') { // Backwards compatibility if ($width && $height) { $mode = 'center_top'; } else { $mode = 'proportional'; } } // Backwards compatibility if ($mode == 'crop') { $mode = 'center_center'; } $strCacheKey = substr(md5('-w' . $width . '-h' . $height . '-' . $image . '-' . $mode . '-' . $objFile->mtime), 0, 8); $strCacheName = 'assets/images/' . substr($strCacheKey, -1) . '/' . $objFile->filename . '-' . $strCacheKey . '.' . $objFile->extension; // Check whether the image exists already if (!\Config::get('debugMode')) { // Custom target (thanks to Tristan Lins) (see #4166) if ($target && !$force) { if (file_exists(TL_ROOT . '/' . $target) && $objFile->mtime <= filemtime(TL_ROOT . '/' . $target)) { return \System::urlEncode($target); } } // Regular cache file if (file_exists(TL_ROOT . '/' . $strCacheName)) { // Copy the cached file if it exists if ($target) { \Files::getInstance()->copy($strCacheName, $target); return \System::urlEncode($target); } return \System::urlEncode($strCacheName); } } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['getImage']) && is_array($GLOBALS['TL_HOOKS']['getImage'])) { foreach ($GLOBALS['TL_HOOKS']['getImage'] as $callback) { $return = \System::importStatic($callback[0])->{$callback}[1]($image, $width, $height, $mode, $strCacheName, $objFile, $target); if (is_string($return)) { return \System::urlEncode($return); } } } // Return the path to the original image if the GDlib cannot handle it if (!extension_loaded('gd') || !$objFile->isGdImage || $objFile->width > \Config::get('gdMaxImgWidth') || $objFile->height > \Config::get('gdMaxImgHeight') || !$width && !$height || $width > \Config::get('gdMaxImgWidth') || $height > \Config::get('gdMaxImgHeight')) { return \System::urlEncode($image); } $intPositionX = 0; $intPositionY = 0; $intWidth = $width; $intHeight = $height; // Mode-specific changes if ($intWidth && $intHeight) { switch ($mode) { case 'proportional': if ($objFile->width >= $objFile->height) { unset($height, $intHeight); } else { unset($width, $intWidth); } break; case 'box': if (round($objFile->height * $width / $objFile->width) <= $intHeight) { unset($height, $intHeight); } else { unset($width, $intWidth); } break; } } $strNewImage = null; $strSourceImage = null; // Resize width and height and crop the image if necessary if ($intWidth && $intHeight) { if ($intWidth * $objFile->height != $intHeight * $objFile->width) { $intWidth = max(round($objFile->width * $height / $objFile->height), 1); $intPositionX = -intval(($intWidth - $width) / 2); if ($intWidth < $width) { $intWidth = $width; $intHeight = max(round($objFile->height * $width / $objFile->width), 1); $intPositionX = 0; $intPositionY = -intval(($intHeight - $height) / 2); } } // Advanced crop modes switch ($mode) { case 'left_top': $intPositionX = 0; $intPositionY = 0; break; case 'center_top': $intPositionX = -intval(($intWidth - $width) / 2); $intPositionY = 0; break; case 'right_top': $intPositionX = -intval($intWidth - $width); $intPositionY = 0; break; case 'left_center': $intPositionX = 0; $intPositionY = -intval(($intHeight - $height) / 2); break; case 'center_center': $intPositionX = -intval(($intWidth - $width) / 2); $intPositionY = -intval(($intHeight - $height) / 2); break; case 'right_center': $intPositionX = -intval($intWidth - $width); $intPositionY = -intval(($intHeight - $height) / 2); break; case 'left_bottom': $intPositionX = 0; $intPositionY = -intval($intHeight - $height); break; case 'center_bottom': $intPositionX = -intval(($intWidth - $width) / 2); $intPositionY = -intval($intHeight - $height); break; case 'right_bottom': $intPositionX = -intval($intWidth - $width); $intPositionY = -intval($intHeight - $height); break; } $strNewImage = imagecreatetruecolor($width, $height); } elseif ($intWidth) { $intHeight = max(round($objFile->height * $width / $objFile->width), 1); $strNewImage = imagecreatetruecolor($intWidth, $intHeight); } elseif ($intHeight) { $intWidth = max(round($objFile->width * $height / $objFile->height), 1); $strNewImage = imagecreatetruecolor($intWidth, $intHeight); } $arrGdinfo = gd_info(); $strGdVersion = preg_replace('/[^0-9\\.]+/', '', $arrGdinfo['GD Version']); switch ($objFile->extension) { case 'gif': if ($arrGdinfo['GIF Read Support']) { $strSourceImage = imagecreatefromgif(TL_ROOT . '/' . $image); $intTranspIndex = imagecolortransparent($strSourceImage); // Handle transparency if ($intTranspIndex >= 0 && $intTranspIndex < imagecolorstotal($strSourceImage)) { $arrColor = imagecolorsforindex($strSourceImage, $intTranspIndex); $intTranspIndex = imagecolorallocate($strNewImage, $arrColor['red'], $arrColor['green'], $arrColor['blue']); imagefill($strNewImage, 0, 0, $intTranspIndex); imagecolortransparent($strNewImage, $intTranspIndex); } } break; case 'jpg': case 'jpeg': if ($arrGdinfo['JPG Support'] || $arrGdinfo['JPEG Support']) { $strSourceImage = imagecreatefromjpeg(TL_ROOT . '/' . $image); } break; case 'png': if ($arrGdinfo['PNG Support']) { $strSourceImage = imagecreatefrompng(TL_ROOT . '/' . $image); // Handle transparency (GDlib >= 2.0 required) if (version_compare($strGdVersion, '2.0', '>=')) { imagealphablending($strNewImage, false); $intTranspIndex = imagecolorallocatealpha($strNewImage, 0, 0, 0, 127); imagefill($strNewImage, 0, 0, $intTranspIndex); imagesavealpha($strNewImage, true); } } break; } // The new image could not be created if (!$strSourceImage) { imagedestroy($strNewImage); \System::log('Image "' . $image . '" could not be processed', __METHOD__, TL_ERROR); return null; } imageinterlace($strNewImage, 1); // see #6529 imagecopyresampled($strNewImage, $strSourceImage, $intPositionX, $intPositionY, 0, 0, $intWidth, $intHeight, $objFile->width, $objFile->height); // Fallback to PNG if GIF ist not supported if ($objFile->extension == 'gif' && !$arrGdinfo['GIF Create Support']) { $objFile->extension = 'png'; } // Create the new image switch ($objFile->extension) { case 'gif': imagegif($strNewImage, TL_ROOT . '/' . $strCacheName); break; case 'jpg': case 'jpeg': imagejpeg($strNewImage, TL_ROOT . '/' . $strCacheName, \Config::get('jpgQuality') ?: 80); break; case 'png': // Optimize non-truecolor images (see #2426) if (version_compare($strGdVersion, '2.0', '>=') && function_exists('imagecolormatch') && !imageistruecolor($strSourceImage)) { // TODO: make it work with transparent images, too if (imagecolortransparent($strSourceImage) == -1) { $intColors = imagecolorstotal($strSourceImage); // Convert to a palette image // @see http://www.php.net/manual/de/function.imagetruecolortopalette.php#44803 if ($intColors > 0 && $intColors < 256) { $wi = imagesx($strNewImage); $he = imagesy($strNewImage); $ch = imagecreatetruecolor($wi, $he); imagecopymerge($ch, $strNewImage, 0, 0, 0, 0, $wi, $he, 100); imagetruecolortopalette($strNewImage, false, $intColors); imagecolormatch($ch, $strNewImage); imagedestroy($ch); } } } imagepng($strNewImage, TL_ROOT . '/' . $strCacheName); break; } // Destroy the temporary images imagedestroy($strSourceImage); imagedestroy($strNewImage); // Resize the original image if ($target) { \Files::getInstance()->copy($strCacheName, $target); return \System::urlEncode($target); } // Set the file permissions when the Safe Mode Hack is used if (\Config::get('useFTP')) { \Files::getInstance()->chmod($strCacheName, \Config::get('defaultFileChmod')); } // Return the path to new image return \System::urlEncode($strCacheName); }
/** * Export a theme * * @param \DataContainer $dc */ public function exportTheme($dc) { // Get the theme meta data $objTheme = $this->Database->prepare("SELECT * FROM tl_theme WHERE id=?")->limit(1)->execute($dc->id); if ($objTheme->numRows < 1) { return; } // Romanize the name $strName = utf8_romanize($objTheme->name); $strName = strtolower(str_replace(' ', '_', $strName)); $strName = preg_replace('/[^A-Za-z0-9._-]/', '', $strName); $strName = basename($strName); // Create a new XML document $xml = new \DOMDocument('1.0', 'UTF-8'); $xml->formatOutput = true; // Root element $tables = $xml->createElement('tables'); $tables = $xml->appendChild($tables); // Add the tables $this->addTableTlTheme($xml, $tables, $objTheme); $this->addTableTlStyleSheet($xml, $tables, $objTheme); $this->addTableTlModule($xml, $tables, $objTheme); $this->addTableTlLayout($xml, $tables, $objTheme); $this->addTableTlImageSize($xml, $tables, $objTheme); // Generate the archive $strTmp = md5(uniqid(mt_rand(), true)); $objArchive = new \ZipWriter('system/tmp/' . $strTmp); // Add the files $this->addTableTlFiles($xml, $tables, $objTheme, $objArchive); // Add the template files $this->addTemplatesToArchive($objArchive, $objTheme->templates); // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['exportTheme']) && is_array($GLOBALS['TL_HOOKS']['exportTheme'])) { foreach ($GLOBALS['TL_HOOKS']['exportTheme'] as $callback) { \System::importStatic($callback[0])->{$callback}[1]($xml, $objArchive, $objTheme->id); } } // Add the XML document $objArchive->addString($xml->saveXML(), 'theme.xml'); // Close the archive $objArchive->close(); // Open the "save as …" dialogue $objFile = new \File('system/tmp/' . $strTmp, true); $objFile->sendToBrowser($strName . '.cto'); }
/** * Adds a form field * * @param string $strName the form field name * @param array $arrDca The DCA representation of the field * @param ArrayPosition $position * * @return $this */ public function addFormField($strName, array $arrDca, ArrayPosition $position = null) { $this->checkFormFieldNameIsValid($strName); if (null === $position) { $position = ArrayPosition::last(); } // Make sure it has a "name" attribute because it is mandatory if (!isset($arrDca['name'])) { $arrDca['name'] = $strName; } // Support default values if (!$this->isSubmitted()) { if (isset($arrDca['default']) && !isset($arrDca['value'])) { $arrDca['value'] = $arrDca['default']; } // Try to load the default value from bound Model if (!$arrDca['ignoreModelValue'] && $this->objModel !== null) { $arrDca['value'] = $this->objModel->{$strName}; } } if (!isset($arrDca['inputType'])) { throw new \RuntimeException(sprintf('You did not specify any inputType for the field "%s"!', $strName)); } /** @type \Widget $strClass */ $strClass = $GLOBALS['TL_FFL'][$arrDca['inputType']]; if (!class_exists($strClass)) { throw new \RuntimeException(sprintf('The class "%s" for type "%s" could not be found.', $strClass, $arrDca['inputType'])); } // Convert date formats into timestamps $rgxp = $arrDca['eval']['rgxp']; if (in_array($rgxp, array('date', 'time', 'datim'))) { $this->addValidator($strName, function ($varValue) use($rgxp) { if ($varValue != '') { $key = $rgxp . 'Format'; $format = isset($GLOBALS['objPage']) ? $GLOBALS['objPage']->{$key} : $GLOBALS['TL_CONFIG'][$key]; $objDate = new \Date($varValue, $format); $varValue = $objDate->tstamp; } return $varValue; }); } if (is_array($arrDca['save_callback'])) { $this->addValidator($strName, function ($varValue, \Widget $objWidget, Form $objForm) use($arrDca, $strName) { $intId = 0; $strTable = ''; if (($objModel = $objForm->getBoundModel()) !== null) { $intId = $objModel->id; $strTable = $objModel->getTable(); } $dc = (object) array('id' => $intId, 'table' => $strTable, 'value' => $varValue, 'field' => $strName, 'inputName' => $objWidget->name, 'activeRecord' => $objModel); foreach ($arrDca['save_callback'] as $callback) { if (is_array($callback)) { $objCallback = \System::importStatic($callback[0]); $varValue = $objCallback->{$callback[1]}($varValue, $dc); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $dc); } } return $varValue; }); } $arrDca = $strClass::getAttributesFromDca($arrDca, $arrDca['name'], $arrDca['value']); // Convert optgroups so they work with FormSelectMenu if (is_array($arrDca['options']) && array_is_assoc($arrDca['options'])) { $arrOptions = $arrDca['options']; $arrDca['options'] = array(); foreach ($arrOptions as $k => $v) { if (isset($v['label'])) { $arrDca['options'][] = $v; } else { $arrDca['options'][] = array('label' => $k, 'value' => $k, 'group' => '1'); foreach ($v as $vv) { $arrDca['options'][] = $vv; } } } } $this->arrFormFields = $position->addToArray($this->arrFormFields, array($strName => $arrDca)); $this->intState = self::STATE_DIRTY; return $this; }
/** * Generate surcharges for a collection * * Process: * 1. Collect surcharges (e.g. shipping and billing) from Isotope core and submodules using hook * 2. Split surcharges by "with or without tax" * => surcharges without tax are placed after tax surcharges and ignored in the complex compilation step * 3. Run through all product collection items and calculate their tax amount * 4. Run through all surcharges with tax and calculate their tax amount * * @param IsotopeProductCollection|\Isotope\Model\ProductCollection\Order $objCollection * * @return array */ public static function findForCollection(IsotopeProductCollection $objCollection) { $arrPreTax = array(); $arrPostTax = array(); // !HOOK: get collection surcharges if (isset($GLOBALS['ISO_HOOKS']['findSurchargesForCollection']) && is_array($GLOBALS['ISO_HOOKS']['findSurchargesForCollection'])) { foreach ($GLOBALS['ISO_HOOKS']['findSurchargesForCollection'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrResult = $objCallback->{$callback[1]}($objCollection); foreach ($arrResult as $objSurcharge) { if (!$objSurcharge instanceof IsotopeProductCollectionSurcharge || $objSurcharge instanceof Tax) { throw new \InvalidArgumentException('Instance of ' . get_class($objSurcharge) . ' is not a valid product collection surcharge.'); } if ($objSurcharge->hasTax()) { $arrPreTax[] = $objSurcharge; } else { $arrPostTax[] = $objSurcharge; } } } } $arrTaxes = array(); $arrAddresses = array('billing' => $objCollection->getBillingAddress()); static::addTaxesForItems($arrTaxes, $objCollection, $arrPreTax, $arrAddresses); static::addTaxesForSurcharges($arrTaxes, $arrPreTax, $arrAddresses); return array_merge($arrPreTax, $arrTaxes, $arrPostTax); }
/** * Import files from selected folder * * @param string $strPath */ protected function importFromPath($strPath) { $arrFiles = scan(TL_ROOT . '/' . $strPath); if (empty($arrFiles)) { \Message::addError($GLOBALS['TL_LANG']['MSC']['noFilesInFolder']); \Controller::reload(); } $blnEmpty = true; $arrDelete = array(); $objProducts = \Database::getInstance()->prepare("SELECT * FROM tl_iso_product WHERE pid=0")->execute(); while ($objProducts->next()) { $arrImageNames = array(); $arrImages = deserialize($objProducts->images); if (!is_array($arrImages)) { $arrImages = array(); } else { foreach ($arrImages as $row) { if ($row['src']) { $arrImageNames[] = $row['src']; } } } $arrPattern = array(); $arrPattern[] = $objProducts->alias ? standardize($objProducts->alias) : null; $arrPattern[] = $objProducts->sku ? $objProducts->sku : null; $arrPattern[] = $objProducts->sku ? standardize($objProducts->sku) : null; $arrPattern[] = !empty($arrImageNames) ? implode('|', $arrImageNames) : null; // !HOOK: add custom import regex patterns if (isset($GLOBALS['ISO_HOOKS']['addAssetImportRegexp']) && is_array($GLOBALS['ISO_HOOKS']['addAssetImportRegexp'])) { foreach ($GLOBALS['ISO_HOOKS']['addAssetImportRegexp'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrPattern = $objCallback->{$callback}[1]($arrPattern, $objProducts); } } $strPattern = '@^(' . implode('|', array_filter($arrPattern)) . ')@i'; $arrMatches = preg_grep($strPattern, $arrFiles); if (!empty($arrMatches)) { $arrNewImages = array(); foreach ($arrMatches as $file) { if (is_dir(TL_ROOT . '/' . $strPath . '/' . $file)) { $arrSubfiles = scan(TL_ROOT . '/' . $strPath . '/' . $file); if (!empty($arrSubfiles)) { foreach ($arrSubfiles as $subfile) { if (is_file($strPath . '/' . $file . '/' . $subfile)) { $objFile = new \File($strPath . '/' . $file . '/' . $subfile); if ($objFile->isGdImage) { $arrNewImages[] = $strPath . '/' . $file . '/' . $subfile; } } } } } elseif (is_file(TL_ROOT . '/' . $strPath . '/' . $file)) { $objFile = new \File($strPath . '/' . $file); if ($objFile->isGdImage) { $arrNewImages[] = $strPath . '/' . $file; } } } if (!empty($arrNewImages)) { foreach ($arrNewImages as $strFile) { $pathinfo = pathinfo(TL_ROOT . '/' . $strFile); // Will recursively create the folder $objFolder = new \Folder('isotope/' . strtolower(substr($pathinfo['filename'], 0, 1))); $strCacheName = $pathinfo['filename'] . '-' . substr(md5_file(TL_ROOT . '/' . $strFile), 0, 8) . '.' . $pathinfo['extension']; \Files::getInstance()->copy($strFile, $objFolder->path . '/' . $strCacheName); $arrImages[] = array('src' => $strCacheName); $arrDelete[] = $strFile; \Message::addConfirmation(sprintf($GLOBALS['TL_LANG']['MSC']['assetImportConfirmation'], $pathinfo['filename'] . '.' . $pathinfo['extension'], $objProducts->name)); $blnEmpty = false; } \Database::getInstance()->prepare("UPDATE tl_iso_product SET images=? WHERE id=?")->execute(serialize($arrImages), $objProducts->id); } } } if (!empty($arrDelete)) { $arrDelete = array_unique($arrDelete); foreach ($arrDelete as $file) { \Files::getInstance()->delete($file); } } if ($blnEmpty) { \Message::addInfo($GLOBALS['TL_LANG']['MSC']['assetImportNoFilesFound']); } \Controller::reload(); }
define('TL_MODE', 'FE'); require '../../../initialize.php'; $intModuleId = (int) \Input::get('module'); if ($intModuleId) { // Find module $objModule = \ModuleModel::findByPk($intModuleId); // Validate module if (!$objModule || $objModule->type !== 'anystores_map') { header('Content-Type: application/json'); echo json_encode(array('status' => 'NO_VALID_MODULE')); exit; } // Hook to manipulate the module if (isset($GLOBALS['TL_HOOKS']['anystores_getAjaxModule']) && is_array($GLOBALS['TL_HOOKS']['anystores_getAjaxModule'])) { foreach ($GLOBALS['TL_HOOKS']['anystores_getAjaxModule'] as $callback) { \System::importStatic($callback[0])->{$callback[1]}($objModule); } } if (\Validator::isBinaryUuid($objModule->anystores_defaultMarker)) { if (($objFile = \FilesModel::findByPk($objModule->anystores_defaultMarker)) !== null) { $objModule->anystores_defaultMarker = $objFile->path; } } // Find stores $objStores = AnyStoresModel::findPublishedByCategory(deserialize($objModule->anystores_categories)); if (!$objStores) { header('Content-Type: application/json'); echo json_encode(array('status' => 'NO_STORES')); exit; } while ($objStores->next()) {
/** * Add the relation filters * @param \DataContainer $dc in BE * @return string */ public function addRelationFilters($dc) { if (empty(static::$arrFilterableFields)) { return ''; } $filter = $GLOBALS['TL_DCA'][$dc->table]['list']['sorting']['mode'] == 4 ? $dc->table . '_' . CURRENT_ID : $dc->table; $session = \Session::getInstance()->getData(); // Set filter from user input if (\Input::post('FORM_SUBMIT') == 'tl_filters') { foreach (array_keys(static::$arrFilterableFields) as $field) { if (\Input::post($field, true) != 'tl_' . $field) { $session['filter'][$filter][$field] = \Input::post($field, true); } else { unset($session['filter'][$filter][$field]); } } \Session::getInstance()->setData($session); } $count = 0; $return = '<div class="tl_filter tl_subpanel"> <strong>' . $GLOBALS['TL_LANG']['HST']['advanced_filter'] . '</strong> '; foreach (static::$arrFilterableFields as $field => $arrRelation) { $return .= '<select name="' . $field . '" class="tl_select' . (isset($session['filter'][$filter][$field]) ? ' active' : '') . '"> <option value="tl_' . $field . '">' . $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['label'][0] . '</option> <option value="tl_' . $field . '">---</option>'; $arrIds = Model::getRelatedValues($arrRelation['reference_table'], $field); if (empty($arrIds)) { $return .= '</select> '; // Add the line-break after 5 elements if (++$count % 5 == 0) { $return .= '<br>'; } continue; } $options = array_unique($arrIds); $options_callback = array(); // Store the field name to be used e.g. in the options_callback $this->field = $field; // Call the options_callback if ((is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback']) || is_callable($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'])) && !$GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference']) { if (is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'])) { $strClass = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'][1]; $objClass = \System::importStatic($strClass); $options_callback = $objClass->{$strMethod}($this); } elseif (is_callable($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'])) { $options_callback = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback']($this); } // Sort options according to the keys of the callback array $options = array_intersect(array_keys($options_callback), $options); } $options_sorter = array(); // Options foreach ($options as $kk => $vv) { $value = $vv; // Options callback if (!empty($options_callback) && is_array($options_callback)) { $vv = $options_callback[$vv]; } elseif (isset($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['foreignKey'])) { // Replace the ID with the foreign key $key = explode('.', $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['foreignKey'], 2); $objParent = \Database::getInstance()->prepare("SELECT " . $key[1] . " AS value FROM " . $key[0] . " WHERE id=?")->limit(1)->execute($vv); if ($objParent->numRows) { $vv = $objParent->value; } } $option_label = ''; // Use reference array if (isset($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'])) { $option_label = is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'][$vv]) ? $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'][$vv][0] : $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'][$vv]; } elseif ($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options'])) { // Associative array $option_label = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options'][$vv]; } // No empty options allowed if (!strlen($option_label)) { $option_label = $vv ?: '-'; } $options_sorter[' <option value="' . specialchars($value) . '"' . (isset($session['filter'][$filter][$field]) && $value == $session['filter'][$filter][$field] ? ' selected="selected"' : '') . '>' . $option_label . '</option>'] = utf8_romanize($option_label); } $return .= "\n" . implode("\n", array_keys($options_sorter)); $return .= '</select> '; // Add the line-break after 5 elements if (++$count % 5 == 0) { $return .= '<br>'; } } return $return . '</div>'; }
/** * Returns an array of all allowed product IDs and variant IDs for the current backend user * @return array|bool */ public static function getAllowedIds() { $objUser = \BackendUser::getInstance(); if ($objUser->isAdmin) { $arrProducts = true; } else { $arrNewRecords = $_SESSION['BE_DATA']['new_records']['tl_iso_product']; $arrProductTypes = $objUser->iso_product_types; $arrGroups = array(); // Return false if there are no product types if (!is_array($arrProductTypes) || empty($arrProductTypes)) { return false; } // Find the user groups if (is_array($objUser->iso_groups) && count($objUser->iso_groups) > 0) { $arrGroups = array_merge($arrGroups, $objUser->iso_groups, \Database::getInstance()->getChildRecords($objUser->iso_groups, Group::getTable())); if (in_array('rootPaste', $objUser->iso_groupp)) { $arrGroups[] = 0; } } $objProducts = \Database::getInstance()->execute("\n SELECT id FROM tl_iso_product\n WHERE pid=0\n AND language=''\n " . (empty($arrGroups) ? '' : "AND gid IN (" . implode(',', $arrGroups) . ")") . "\n AND (\n type IN (" . implode(',', $arrProductTypes) . ")" . (is_array($arrNewRecords) && !empty($arrNewRecords) ? " OR id IN (" . implode(',', $arrNewRecords) . ")" : '') . ")\n "); if ($objProducts->numRows == 0) { return array(); } $arrProducts = $objProducts->fetchEach('id'); $arrProducts = array_merge($arrProducts, \Database::getInstance()->getChildRecords($arrProducts, 'tl_iso_product')); } // HOOK: allow extensions to define allowed products if (isset($GLOBALS['ISO_HOOKS']['getAllowedProductIds']) && is_array($GLOBALS['ISO_HOOKS']['getAllowedProductIds'])) { foreach ($GLOBALS['ISO_HOOKS']['getAllowedProductIds'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrAllowed = $objCallback->{$callback}[1](); if ($arrAllowed === false) { return false; } elseif (is_array($arrAllowed)) { if ($arrProducts === true) { $arrProducts = $arrAllowed; } else { $arrProducts = array_intersect($arrProducts, $arrAllowed); } } } } // If all product are allowed, we don't need to filter if ($arrProducts === true || count($arrProducts) == Product::countAll()) { return true; } return $arrProducts; }
/** * Parse a date format string and translate textual representations * * @param string $strFormat The date format string * @param integer $intTstamp An optional timestamp * * @return string The textual representation of the date */ public static function parse($strFormat, $intTstamp = null) { $strModified = str_replace(array('l', 'D', 'F', 'M'), array('w::1', 'w::2', 'n::3', 'n::4'), $strFormat); if ($intTstamp === null) { $strDate = date($strModified); } elseif (!is_numeric($intTstamp)) { return ''; } else { $strDate = date($strModified, $intTstamp); } $strReturn = static::resolveCustomModifiers($strDate); // HOOK: add custom logic (see #4260) if (isset($GLOBALS['TL_HOOKS']['parseDate']) && is_array($GLOBALS['TL_HOOKS']['parseDate'])) { foreach ($GLOBALS['TL_HOOKS']['parseDate'] as $callback) { $strReturn = \System::importStatic($callback[0])->{$callback[1]}($strReturn, $strFormat, $intTstamp); } } return $strReturn; }