/** * Renders the source code around the error line. * * @param string $file source file path * @param integer $errorLine the error line number * @param integer $maxLines maximum number of lines to display * @return string the rendering result */ public static function renderSourceCode($file, $errorLine, $maxLines) { $errorLine--; // adjust line number to 0-based from 1-based if ($errorLine < 0 || ($lines = @file($file)) === false || ($lineCount = count($lines)) <= $errorLine) { return ''; } $halfLines = (int) ($maxLines / 2); $beginLine = $errorLine - $halfLines > 0 ? $errorLine - $halfLines : 0; $endLine = $errorLine + $halfLines < $lineCount ? $errorLine + $halfLines : $lineCount - 1; $lineNumberWidth = strlen($endLine + 1); $output = ''; for ($i = $beginLine; $i <= $endLine; ++$i) { $isErrorLine = $i === $errorLine; $code = sprintf("<span class=\"ln" . ($isErrorLine ? ' error-ln' : '') . "\">%0{$lineNumberWidth}d</span> %s", $i + 1, HtmlHelper::encode(str_replace("\t", ' ', $lines[$i]))); if (!$isErrorLine) { $output .= $code; } else { $output .= '<span class="error">' . $code . '</span>'; } } return '<div class="code"><pre>' . $output . '</pre></div>'; }
/** * Returns an <img> tag based on this asset. * * @return \Twig_Markup|null */ public function getImg() { if ($this->kind == 'image') { $img = '<img src="' . $this->url . '" width="' . $this->getWidth() . '" height="' . $this->getHeight() . '" alt="' . HtmlHelper::encode($this->title) . '" />'; return TemplateHelper::getRaw($img); } }
/** * Validates a Matrix field's settings. * * If the settings don’t validate, any validation errors will be stored on the settings model. * * @param MatrixSettingsModel $settings The settings model. * * @return bool Whether the settings validated. */ public function validateFieldSettings(MatrixSettingsModel $settings) { $validates = true; $this->_uniqueBlockTypeAndFieldHandles = array(); $uniqueAttributes = array('name', 'handle'); $uniqueAttributeValues = array(); foreach ($settings->getBlockTypes() as $blockType) { if (!$this->validateBlockType($blockType, false)) { // Don't break out of the loop because we still want to get validation errors for the remaining block // types. $validates = false; } // Do our own unique name/handle validation, since the DB-based validation can't be trusted when saving // multiple records at once foreach ($uniqueAttributes as $attribute) { $value = $blockType->{$attribute}; if ($value && (!isset($uniqueAttributeValues[$attribute]) || !in_array($value, $uniqueAttributeValues[$attribute]))) { $uniqueAttributeValues[$attribute][] = $value; } else { $blockType->addError($attribute, Craft::t('{attribute} "{value}" has already been taken.', array('attribute' => $blockType->getAttributeLabel($attribute), 'value' => HtmlHelper::encode($value)))); $validates = false; } } } return $validates; }
/** * Get available Transforms. * * @return array */ private function _getTransforms() { $transforms = craft()->assetTransforms->getAllTransforms('id'); $settings = $this->getSettings(); $transformIds = array_flip(!empty($settings->availableTransforms) && is_array($settings->availableTransforms) ? $settings->availableTransforms : array()); if (!empty($transformIds)) { $transforms = array_intersect_key($transforms, $transformIds); } $transformList = array(); foreach ($transforms as $transform) { $transformList[] = (object) array('handle' => HtmlHelper::encode($transform->handle), 'name' => HtmlHelper::encode($transform->name)); } return $transformList; }
/** * Returns an anchor pre-filled with this element's URL and title. * * @return \Twig_Markup */ public function getLink() { $link = '<a href="' . $this->getUrl() . '">' . HtmlHelper::encode($this->__toString()) . '</a>'; return TemplateHelper::getRaw($link); }
/** * Returns the HTML for an element in the CP. * * @param array &$context * * @return string */ private function _getCpElementHtml(&$context) { if (!isset($context['element'])) { return; } if (!isset($context['context'])) { $context['context'] = 'index'; } if (isset($context['elementType'])) { $elementType = $context['elementType']; } else { $elementType = craft()->elements->getElementType($context['element']->getElementType()); } // How big is the element going to be? if (isset($context['size']) && ($context['size'] == 'small' || $context['size'] == 'large')) { $elementSize = $context['size']; } else { if (isset($context['viewMode']) && $context['viewMode'] == 'thumbs') { $elementSize = 'large'; } else { $elementSize = 'small'; } } // Create the thumb/icon image, if there is one // --------------------------------------------------------------------- $thumbUrl = $context['element']->getThumbUrl(self::$_elementThumbSizes[0]); if ($thumbUrl) { $srcsets = array(); foreach (self::$_elementThumbSizes as $i => $size) { if ($i == 0) { $srcset = $thumbUrl; } else { $srcset = $context['element']->getThumbUrl($size); } $srcsets[] = $srcset . ' ' . $size . 'w'; } $imgHtml = '<div class="elementthumb">' . '<img ' . 'sizes="' . ($elementSize == 'small' ? self::$_elementThumbSizes[0] : self::$_elementThumbSizes[2]) . 'px" ' . 'srcset="' . implode(', ', $srcsets) . '" ' . 'alt="">' . '</div> '; } else { $imgHtml = ''; } $html = '<div class="element ' . $elementSize; if ($context['context'] == 'field') { $html .= ' removable'; } if ($elementType->hasStatuses()) { $html .= ' hasstatus'; } if ($thumbUrl) { $html .= ' hasthumb'; } $label = HtmlHelper::encode($context['element']); $html .= '" data-id="' . $context['element']->id . '" data-locale="' . $context['element']->locale . '" data-status="' . $context['element']->getStatus() . '" data-label="' . $label . '" data-url="' . $context['element']->getUrl() . '"'; if ($context['element']->level) { $html .= ' data-level="' . $context['element']->level . '"'; } $isEditable = ElementHelper::isElementEditable($context['element']); if ($isEditable) { $html .= ' data-editable'; } $html .= '>'; if ($context['context'] == 'field' && isset($context['name'])) { $html .= '<input type="hidden" name="' . $context['name'] . '[]" value="' . $context['element']->id . '">'; $html .= '<a class="delete icon" title="' . Craft::t('Remove') . '"></a> '; } if ($elementType->hasStatuses()) { $html .= '<span class="status ' . $context['element']->getStatus() . '"></span>'; } $html .= $imgHtml; $html .= '<div class="label">'; $html .= '<span class="title">'; if ($context['context'] == 'index' && ($cpEditUrl = $context['element']->getCpEditUrl())) { $cpEditUrl = HtmlHelper::encode($cpEditUrl); $html .= "<a href=\"{$cpEditUrl}\">{$label}</a>"; } else { $html .= $label; } $html .= '</span></div></div>'; return $html; }
/** * Called when a user beings up an entry for editing before being displayed. * * @param array $variables * * @throws HttpException * @return null */ public function actionEditEntry(array $variables = array()) { $this->_prepEditEntryVariables($variables); // Make sure they have permission to edit this entry $this->enforceEditEntryPermissions($variables['entry']); $currentUser = craft()->userSession->getUser(); $variables['permissionSuffix'] = ':' . $variables['entry']->sectionId; if (craft()->getEdition() >= Craft::Client && $variables['section']->type != SectionType::Single) { // Get all the possible authors if ($variables['entry']->authorId) { if ($variables['entry']->authorId == $currentUser->id) { $excludeAuthorIds = 'not ' . $currentUser->id; $excludeAuthorIds = array('and', $excludeAuthorIds, 'not ' . $variables['entry']->authorId); } else { $excludeAuthorIds = array('not ' . $variables['entry']->authorId); } } $authorOptionCriteria = craft()->elements->getCriteria(ElementType::User); $authorOptionCriteria->can = 'editEntries' . $variables['permissionSuffix']; $authorOptionCriteria->limit = null; if ($variables['entry']->authorId) { $authorOptionCriteria->id = $excludeAuthorIds; } $authorOptions = $authorOptionCriteria->find(); // List the current author first if ($variables['entry']->authorId && $variables['entry']->authorId != $currentUser->id) { $currentAuthor = craft()->users->getUserById($variables['entry']->authorId); if ($currentAuthor) { array_unshift($authorOptions, $currentAuthor); } } // Then the current user if (!$variables['entry']->authorId || $variables['entry']->authorId == $currentUser->id) { array_unshift($authorOptions, $currentUser); } $variables['authorOptions'] = array(); foreach ($authorOptions as $authorOption) { $authorLabel = $authorOption->username; $authorFullName = $authorOption->getFullName(); if ($authorFullName) { $authorLabel .= ' - ' . $authorFullName; } $variables['authorOptions'][] = array('label' => $authorLabel, 'value' => $authorOption->id); } } if (craft()->getEdition() >= Craft::Client && $variables['section']->type == SectionType::Structure) { // Get all the possible parent options $parentOptionCriteria = craft()->elements->getCriteria(ElementType::Entry); $parentOptionCriteria->sectionId = $variables['section']->id; $parentOptionCriteria->status = null; $parentOptionCriteria->localeEnabled = null; $parentOptionCriteria->limit = null; if ($variables['section']->maxLevels) { $parentOptionCriteria->level = '< ' . $variables['section']->maxLevels; } if ($variables['entry']->id) { $idParam = array('and', 'not ' . $variables['entry']->id); $descendantCriteria = craft()->elements->getCriteria(ElementType::Entry); $descendantCriteria->descendantOf = $variables['entry']; $descendantCriteria->status = null; $descendantCriteria->localeEnabled = null; $descendantIds = $descendantCriteria->ids(); foreach ($descendantIds as $id) { $idParam[] = 'not ' . $id; } $parentOptionCriteria->id = $idParam; } $parentOptions = $parentOptionCriteria->find(); $variables['parentOptions'] = array(array('label' => '', 'value' => '0')); foreach ($parentOptions as $parentOption) { $label = ''; for ($i = 1; $i < $parentOption->level; $i++) { $label .= ' '; } $label .= $parentOption->title; $variables['parentOptions'][] = array('label' => $label, 'value' => $parentOption->id); } // Get the initially selected parent $variables['parentId'] = craft()->request->getParam('parentId'); if ($variables['parentId'] === null && $variables['entry']->id) { $parentIdCriteria = craft()->elements->getCriteria(ElementType::Entry); $parentIdCriteria->ancestorOf = $variables['entry']; $parentIdCriteria->ancestorDist = 1; $parentIdCriteria->status = null; $parentIdCriteria->localeEnabled = null; $parentIds = $parentIdCriteria->ids(); if ($parentIds) { $variables['parentId'] = $parentIds[0]; } } } // Get the enabled locales if (craft()->isLocalized()) { if ($variables['entry']->id) { $variables['enabledLocales'] = craft()->elements->getEnabledLocalesForElement($variables['entry']->id); } else { $variables['enabledLocales'] = array(); foreach ($variables['section']->getLocales() as $locale) { if ($locale->enabledByDefault) { $variables['enabledLocales'][] = $locale->locale; } } } } // Page title w/ revision label if (craft()->getEdition() >= Craft::Client) { switch ($variables['entry']->getClassHandle()) { case 'EntryDraft': $variables['revisionLabel'] = $variables['entry']->name; break; case 'EntryVersion': $variables['revisionLabel'] = Craft::t('Version {num}', array('num' => $variables['entry']->num)); break; default: $variables['revisionLabel'] = Craft::t('Current'); } } if (!$variables['entry']->id) { $variables['title'] = Craft::t('Create a new entry'); } else { $variables['docTitle'] = Craft::t($variables['entry']->title); $variables['title'] = HtmlHelper::encode(Craft::t($variables['entry']->title)); if (craft()->getEdition() >= Craft::Client && $variables['entry']->getClassHandle() != 'Entry') { $variables['title'] .= ' <span class="hidden">(' . $variables['revisionLabel'] . ')</span>'; } } // Breadcrumbs $variables['crumbs'] = array(array('label' => Craft::t('Entries'), 'url' => UrlHelper::getUrl('entries'))); if ($variables['section']->type == SectionType::Single) { $variables['crumbs'][] = array('label' => Craft::t('Singles'), 'url' => UrlHelper::getUrl('entries/singles')); } else { $variables['crumbs'][] = array('label' => Craft::t($variables['section']->name), 'url' => UrlHelper::getUrl('entries/' . $variables['section']->handle)); if ($variables['section']->type == SectionType::Structure) { foreach ($variables['entry']->getAncestors() as $ancestor) { $variables['crumbs'][] = array('label' => $ancestor->title, 'url' => $ancestor->getCpEditUrl()); } } } // Multiple entry types? $entryTypes = $variables['section']->getEntryTypes(); if (count($entryTypes) > 1) { $variables['showEntryTypes'] = true; foreach ($entryTypes as $entryType) { $variables['entryTypeOptions'][] = array('label' => Craft::t($entryType->name), 'value' => $entryType->id); } craft()->templates->includeJsResource('js/EntryTypeSwitcher.js'); craft()->templates->includeJs('new Craft.EntryTypeSwitcher();'); } else { $variables['showEntryTypes'] = false; } // Enable preview mode? if (!craft()->request->isMobileBrowser(true) && craft()->sections->isSectionTemplateValid($variables['section'])) { craft()->templates->includeJsResource('js/LivePreview.js'); craft()->templates->includeJs('Craft.livePreview = new Craft.LivePreview(' . JsonHelper::encode($variables['entry']->getUrl()) . ', "' . $variables['entry']->locale . '");'); $variables['showPreviewBtn'] = true; // Should we show the Share button too? if ($variables['entry']->id) { $classHandle = $variables['entry']->getClassHandle(); // If we're looking at the live version of an entry, just use // the entry's main URL as its share URL if ($classHandle == 'Entry' && $variables['entry']->getStatus() == EntryModel::LIVE) { $variables['shareUrl'] = $variables['entry']->getUrl(); } else { switch ($classHandle) { case 'EntryDraft': $shareParams = array('draftId' => $variables['entry']->draftId); break; case 'EntryVersion': $shareParams = array('versionId' => $variables['entry']->versionId); break; default: $shareParams = array('entryId' => $variables['entry']->id, 'locale' => $variables['entry']->locale); break; } $variables['shareUrl'] = UrlHelper::getActionUrl('entries/shareEntry', $shareParams); } } } else { $variables['showPreviewBtn'] = false; } // Set the base CP edit URL // Can't just use the entry's getCpEditUrl() because that might include the locale ID when we don't want it $variables['baseCpEditUrl'] = 'entries/' . $variables['section']->handle . '/{id}-{slug}'; // Set the "Continue Editing" URL $variables['continueEditingUrl'] = $variables['baseCpEditUrl'] . (isset($variables['draftId']) ? '/drafts/' . $variables['draftId'] : '') . (craft()->isLocalized() && craft()->getLanguage() != $variables['localeId'] ? '/' . $variables['localeId'] : ''); // Can the user delete the entry? $variables['canDeleteEntry'] = $variables['entry']->id && ($variables['entry']->authorId == $currentUser->id && $currentUser->can('deleteEntries' . $variables['permissionSuffix']) || $variables['entry']->authorId != $currentUser->id && $currentUser->can('deletePeerEntries' . $variables['permissionSuffix'])); // Include translations craft()->templates->includeTranslations('Live Preview'); // Render the template! craft()->templates->includeCssResource('css/entry.css'); $this->renderTemplate('entries/_edit', $variables); }
/** * @inheritDoc IElementType::getTableAttributeHtml() * * @param BaseElementModel $element * @param string $attribute * * @return mixed|string */ public function getTableAttributeHtml(BaseElementModel $element, $attribute) { switch ($attribute) { case 'link': $url = $element->getUrl(); if ($url) { return '<a href="' . $url . '" target="_blank" data-icon="world" title="' . Craft::t('Visit webpage') . '"></a>'; } else { return ''; } case 'uri': $url = $element->getUrl(); if ($url) { $value = $element->uri; if ($value == '__home__') { $value = '<span data-icon="home" title="' . Craft::t('Homepage') . '"></span>'; } else { // Add some <wbr> tags in there so it doesn't all have to be on one line $find = array('/'); $replace = array('/<wbr>'); $wordSeparator = craft()->config->get('slugWordSeparator'); if ($wordSeparator) { $find[] = $wordSeparator; $replace[] = $wordSeparator . '<wbr>'; } $value = str_replace($find, $replace, $value); } return '<a href="' . $url . '" target="_blank" class="go" title="' . Craft::t('Visit webpage') . '"><span dir="ltr">' . $value . '</span></a>'; } else { return ''; } default: // Is this a custom field? if (preg_match('/^field:(\\d+)$/', $attribute, $matches)) { $fieldId = $matches[1]; $field = craft()->fields->getFieldById($fieldId); if ($field) { $fieldType = $field->getFieldType(); if ($fieldType && $fieldType instanceof IPreviewableFieldType) { // Was this field value eager-loaded? if ($fieldType instanceof IEagerLoadingFieldType && $element->hasEagerLoadedElements($field->handle)) { $value = $element->getEagerLoadedElements($field->handle); } else { $value = $element->getFieldValue($field->handle); } $fieldType->setElement($element); return $fieldType->getTableAttributeHtml($value); } } return ''; } $value = $element->{$attribute}; if ($value instanceof DateTime) { return '<span title="' . $value->localeDate() . ' ' . $value->localeTime() . '">' . $value->uiTimestamp() . '</span>'; } return HtmlHelper::encode($value); } }
/** * Returns the HTML for an element in the CP. * * @param array &$context * * @return string */ private function _getCpElementHtml(&$context) { if (!isset($context['element'])) { return; } if (!isset($context['context'])) { $context['context'] = 'index'; } if (!isset($context['viewMode'])) { $context['viewMode'] = 'table'; } $thumbClass = 'elementthumb' . $context['element']->id; $iconClass = 'elementicon' . $context['element']->id; if ($context['viewMode'] == 'thumbs') { $thumbSize = 100; $iconSize = 90; $thumbSelectorPrefix = '.thumbsview '; } else { $thumbSize = 30; $iconSize = 20; $thumbSelectorPrefix = ''; } $thumbUrl = $context['element']->getThumbUrl($thumbSize); if ($thumbUrl) { $this->includeCss($thumbSelectorPrefix . '.' . $thumbClass . " { background-image: url('" . $thumbUrl . "'); }"); $this->includeHiResCss($thumbSelectorPrefix . '.' . $thumbClass . " { background-image: url('" . $context['element']->getThumbUrl($thumbSize * 2) . "'); background-size: " . $thumbSize . 'px; }'); } else { $iconUrl = $context['element']->getIconUrl($iconSize); if ($iconUrl) { $this->includeCss($thumbSelectorPrefix . '.' . $iconClass . " { background-image: url('" . $iconUrl . "'); }"); $this->includeHiResCss($thumbSelectorPrefix . '.' . $iconClass . " { background-image: url('" . $context['element']->getIconUrl($iconSize * 2) . "); background-size: " . $iconSize . 'px; }'); } } $html = '<div class="element'; if ($context['context'] == 'field') { $html .= ' removable'; } if ($thumbUrl) { $html .= ' hasthumb'; } else { if ($iconUrl) { $html .= ' hasicon'; } } $label = HtmlHelper::encode($context['element']); $html .= '" data-id="' . $context['element']->id . '" data-locale="' . $context['element']->locale . '" data-status="' . $context['element']->getStatus() . '" data-label="' . $label . '" data-url="' . $context['element']->getUrl() . '"'; if ($context['element']->level) { $html .= ' data-level="' . $context['element']->level . '"'; } $isEditable = ElementHelper::isElementEditable($context['element']); if ($isEditable) { $html .= ' data-editable'; } $html .= '>'; if ($context['context'] == 'field' && isset($context['name'])) { $html .= '<input type="hidden" name="' . $context['name'] . '[]" value="' . $context['element']->id . '">'; $html .= '<a class="delete icon" title="' . Craft::t('Remove') . '"></a> '; } if ($thumbUrl) { $html .= '<div class="elementthumb ' . $thumbClass . '"></div> '; } else { if ($iconUrl) { $html .= '<div class="elementicon ' . $iconClass . '"></div> '; } } $html .= '<div class="label">'; if (isset($context['elementType'])) { $elementType = $context['elementType']; } else { $elementType = craft()->elements->getElementType($context['element']->getElementType()); } if ($elementType->hasStatuses()) { $html .= '<span class="status ' . $context['element']->getStatus() . '"></span>'; } $html .= '<span class="title">'; if ($context['context'] == 'index' && ($cpEditUrl = $context['element']->getCpEditUrl())) { $html .= '<a href="' . $cpEditUrl . '">' . $label . '</a>'; } else { $html .= $label; } $html .= '</span></div></div>'; return $html; }
/** * Get information about available transforms. * * @return null */ public function actionGetTransformInfo() { $this->requireAjaxRequest(); $transforms = craft()->assetTransforms->getAllTransforms(); $output = array(); foreach ($transforms as $transform) { $output[] = (object) array('id' => $transform->id, 'handle' => HtmlHelper::encode($transform->handle), 'name' => HtmlHelper::encode($transform->name)); } $this->returnJson($output); }
/** * @inheritDoc IElementType::getTableAttributeHtml() * * @param BaseElementModel $element * @param string $attribute * * @return mixed|string */ public function getTableAttributeHtml(BaseElementModel $element, $attribute) { switch ($attribute) { case 'uri': $url = $element->getUrl(); if ($url) { $value = $element->uri; if ($value == '__home__') { $value = '<span data-icon="home" title="' . Craft::t('Homepage') . '"></span>'; } else { // Add some <wbr> tags in there so it doesn't all have to be on one line $find = array('/'); $replace = array('/<wbr>'); $wordSeparator = craft()->config->get('slugWordSeparator'); if ($wordSeparator) { $find[] = $wordSeparator; $replace[] = $wordSeparator . '<wbr>'; } $value = str_replace($find, $replace, $value); } return '<a href="' . $url . '" target="_blank" class="go"><span dir="ltr">' . $value . '</span></a>'; } else { return ''; } default: $value = $element->{$attribute}; if ($value instanceof DateTime) { return '<span title="' . $value->localeDate() . ' ' . $value->localeTime() . '">' . $value->uiTimestamp() . '</span>'; } return HtmlHelper::encode($value); } }
/** * Returns a helper function formatting a value as time. * @return \Closure A function formatting a value as time. */ public function getTime() : \Closure { return function ($value, \Mustache_LambdaHelper $helper) { $args = $this->parseArguments($helper->render($value), 'value', ['format' => null]); return HtmlHelper::encode(\Yii::$app->getFormatter()->asTime($args['value'], $args['format'])); }; }