/** * @inheritDoc IWidget::getBodyHtml() * * @return string|false */ public function getBodyHtml() { craft()->templates->includeTranslations('Entry saved.', 'Couldn’t save entry.'); craft()->templates->includeJsResource('js/QuickPostWidget.js'); $section = $this->_getSection(); if (!$section) { return '<p>' . Craft::t('No section has been selected yet.') . '</p>'; } $entryTypes = $section->getEntryTypes('id'); if (!$entryTypes) { return '<p>' . Craft::t('No entry types exist for this section.') . '</p>'; } if ($this->getSettings()->entryType && isset($entryTypes[$this->getSettings()->entryType])) { $entryTypeId = $this->getSettings()->entryType; } else { $entryTypeId = ArrayHelper::getFirstKey($entryTypes); } $entryType = $entryTypes[$entryTypeId]; $params = array('sectionId' => $section->id, 'typeId' => $entryTypeId); craft()->templates->startJsBuffer(); $html = craft()->templates->render('_components/widgets/QuickPost/body', array('section' => $section, 'entryType' => $entryType, 'settings' => $this->getSettings())); $fieldJs = craft()->templates->clearJsBuffer(false); craft()->templates->includeJs('new Craft.QuickPostWidget(' . $this->model->id . ', ' . JsonHelper::encode($params) . ', ' . "function() {\n" . $fieldJs . "\n});"); return $html; }
/** * Saves a section. * * @param SectionModel $section * * @throws \Exception * @return bool */ public function saveSection(SectionModel $section) { if ($section->id) { $sectionRecord = SectionRecord::model()->with('structure')->findById($section->id); if (!$sectionRecord) { throw new Exception(Craft::t('No section exists with the ID “{id}”.', array('id' => $section->id))); } $oldSection = SectionModel::populateModel($sectionRecord); $isNewSection = false; } else { $sectionRecord = new SectionRecord(); $isNewSection = true; } // Shared attributes $sectionRecord->name = $section->name; $sectionRecord->handle = $section->handle; $sectionRecord->type = $section->type; $sectionRecord->enableVersioning = $section->enableVersioning; // Type-specific attributes if ($section->type == SectionType::Single) { $sectionRecord->hasUrls = $section->hasUrls = true; } else { $sectionRecord->hasUrls = $section->hasUrls; } if ($section->hasUrls) { $sectionRecord->template = $section->template; } else { $sectionRecord->template = $section->template = null; } $sectionRecord->validate(); $section->addErrors($sectionRecord->getErrors()); // Make sure that all of the URL formats are set properly $sectionLocales = $section->getLocales(); if (!$sectionLocales) { $section->addError('localeErrors', Craft::t('At least one locale must be selected for the section.')); } $firstSectionLocale = null; foreach ($sectionLocales as $localeId => $sectionLocale) { // Is this the first one? if ($firstSectionLocale === null) { $firstSectionLocale = $sectionLocale; } if ($section->type == SectionType::Single) { $errorKey = 'urlFormat-' . $localeId; if (empty($sectionLocale->urlFormat)) { $section->addError($errorKey, Craft::t('URI cannot be blank.')); } else { if ($section) { // Make sure no other elements are using this URI already $query = craft()->db->createCommand()->from('elements_i18n elements_i18n')->where(array('and', 'elements_i18n.locale = :locale', 'elements_i18n.uri = :uri'), array(':locale' => $localeId, ':uri' => $sectionLocale->urlFormat)); if ($section->id) { $query->join('entries entries', 'entries.id = elements_i18n.elementId')->andWhere('entries.sectionId != :sectionId', array(':sectionId' => $section->id)); } $count = $query->count('elements_i18n.id'); if ($count) { $section->addError($errorKey, Craft::t('This URI is already in use.')); } } } $sectionLocale->nestedUrlFormat = null; } else { if ($section->hasUrls) { $urlFormatAttributes = array('urlFormat'); $sectionLocale->urlFormatIsRequired = true; if ($section->type == SectionType::Structure && $section->maxLevels != 1) { $urlFormatAttributes[] = 'nestedUrlFormat'; $sectionLocale->nestedUrlFormatIsRequired = true; } else { $sectionLocale->nestedUrlFormat = null; } foreach ($urlFormatAttributes as $attribute) { if (!$sectionLocale->validate(array($attribute))) { $section->addError($attribute . '-' . $localeId, $sectionLocale->getError($attribute)); } } } else { $sectionLocale->urlFormat = null; $sectionLocale->nestedUrlFormat = null; } } } if (!$section->hasErrors()) { $transaction = craft()->db->getCurrentTransaction() === null ? craft()->db->beginTransaction() : null; try { // Fire an 'onBeforeSaveSection' event $event = new Event($this, array('section' => $section, 'isNewSection' => $isNewSection)); $this->onBeforeSaveSection($event); // Is the event giving us the go-ahead? if ($event->performAction) { // Do we need to create a structure? if ($section->type == SectionType::Structure) { if (!$isNewSection && $oldSection->type == SectionType::Structure) { $structure = craft()->structures->getStructureById($oldSection->structureId); $isNewStructure = false; } if (empty($structure)) { $structure = new StructureModel(); $isNewStructure = true; } $structure->maxLevels = $section->maxLevels; craft()->structures->saveStructure($structure); $sectionRecord->structureId = $structure->id; $section->structureId = $structure->id; } else { if (!$isNewSection && $oldSection->structureId) { // Delete the old one craft()->structures->deleteStructureById($oldSection->structureId); $sectionRecord->structureId = null; } } $sectionRecord->save(false); // Now that we have a section ID, save it on the model if ($isNewSection) { $section->id = $sectionRecord->id; } // Might as well update our cache of the section while we have it. (It's possible that the URL format //includes {section.handle} or something...) $this->_sectionsById[$section->id] = $section; // Update the sections_i18n table $newLocaleData = array(); if (!$isNewSection) { // Get the old section locales $oldSectionLocaleRecords = SectionLocaleRecord::model()->findAllByAttributes(array('sectionId' => $section->id)); $oldSectionLocales = SectionLocaleModel::populateModels($oldSectionLocaleRecords, 'locale'); } foreach ($sectionLocales as $localeId => $locale) { // Was this already selected? if (!$isNewSection && isset($oldSectionLocales[$localeId])) { $oldLocale = $oldSectionLocales[$localeId]; // Has anything changed? if ($locale->enabledByDefault != $oldLocale->enabledByDefault || $locale->urlFormat != $oldLocale->urlFormat || $locale->nestedUrlFormat != $oldLocale->nestedUrlFormat) { craft()->db->createCommand()->update('sections_i18n', array('enabledByDefault' => (int) $locale->enabledByDefault, 'urlFormat' => $locale->urlFormat, 'nestedUrlFormat' => $locale->nestedUrlFormat), array('id' => $oldLocale->id)); } } else { $newLocaleData[] = array($section->id, $localeId, (int) $locale->enabledByDefault, $locale->urlFormat, $locale->nestedUrlFormat); } } // Insert the new locales craft()->db->createCommand()->insertAll('sections_i18n', array('sectionId', 'locale', 'enabledByDefault', 'urlFormat', 'nestedUrlFormat'), $newLocaleData); if (!$isNewSection) { // Drop any locales that are no longer being used, as well as the associated entry/element locale // rows $droppedLocaleIds = array_diff(array_keys($oldSectionLocales), array_keys($sectionLocales)); if ($droppedLocaleIds) { craft()->db->createCommand()->delete('sections_i18n', array('and', 'sectionId = :sectionId', array('in', 'locale', $droppedLocaleIds)), array(':sectionId' => $section->id)); } } // Make sure there's at least one entry type for this section $entryTypeId = null; if (!$isNewSection) { // Let's grab all of the entry type IDs to save ourselves a query down the road if this is a Single $entryTypeIds = craft()->db->createCommand()->select('id')->from('entrytypes')->where('sectionId = :sectionId', array(':sectionId' => $section->id))->queryColumn(); if ($entryTypeIds) { $entryTypeId = array_shift($entryTypeIds); } } if (!$entryTypeId) { $entryType = new EntryTypeModel(); $entryType->sectionId = $section->id; $entryType->name = $section->name; $entryType->handle = $section->handle; if ($section->type == SectionType::Single) { $entryType->hasTitleField = false; $entryType->titleLabel = null; $entryType->titleFormat = '{section.name|raw}'; } else { $entryType->hasTitleField = true; $entryType->titleLabel = Craft::t('Title'); $entryType->titleFormat = null; } $this->saveEntryType($entryType); $entryTypeId = $entryType->id; } // Now, regardless of whether the section type changed or not, let the section type make sure // everything is cool switch ($section->type) { case SectionType::Single: // Make sure that there is one and only one Entry Type and Entry for this section. $singleEntryId = null; if (!$isNewSection) { // Make sure there's only one entry in this section $entryIds = craft()->db->createCommand()->select('id')->from('entries')->where('sectionId = :sectionId', array(':sectionId' => $section->id))->queryColumn(); if ($entryIds) { $singleEntryId = array_shift($entryIds); // If there are any more, get rid of them if ($entryIds) { craft()->elements->deleteElementById($entryIds); } // Make sure it's enabled and all that. craft()->db->createCommand()->update('elements', array('enabled' => 1, 'archived' => 0), array('id' => $singleEntryId)); craft()->db->createCommand()->update('entries', array('typeId' => $entryTypeId, 'authorId' => null, 'postDate' => DateTimeHelper::currentTimeForDb(), 'expiryDate' => null), array('id' => $singleEntryId)); } // Make sure there's only one entry type for this section if ($entryTypeIds) { $this->deleteEntryTypeById($entryTypeIds); } } if (!$singleEntryId) { // Create it, baby $singleEntry = new EntryModel(); $singleEntry->locale = $firstSectionLocale->locale; $singleEntry->sectionId = $section->id; $singleEntry->typeId = $entryTypeId; $singleEntry->getContent()->title = $section->name; craft()->entries->saveEntry($singleEntry); } break; case SectionType::Structure: if (!$isNewSection && $isNewStructure) { // Add all of the entries to the structure $criteria = craft()->elements->getCriteria(ElementType::Entry); $criteria->locale = ArrayHelper::getFirstKey($oldSectionLocales); $criteria->sectionId = $section->id; $criteria->status = null; $criteria->localeEnabled = null; $criteria->order = 'elements.id'; $criteria->limit = 25; do { $batchEntries = $criteria->find(); foreach ($batchEntries as $entry) { craft()->structures->appendToRoot($section->structureId, $entry, 'insert'); } $criteria->offset += 25; } while ($batchEntries); } break; } // Finally, deal with the existing entries... if (!$isNewSection) { $criteria = craft()->elements->getCriteria(ElementType::Entry); // Get the most-primary locale that this section was already enabled in $locales = array_values(array_intersect(craft()->i18n->getSiteLocaleIds(), array_keys($oldSectionLocales))); if ($locales) { $criteria->locale = $locales[0]; $criteria->sectionId = $section->id; $criteria->status = null; $criteria->localeEnabled = null; $criteria->limit = null; craft()->tasks->createTask('ResaveElements', Craft::t('Resaving {section} entries', array('section' => $section->name)), array('elementType' => ElementType::Entry, 'criteria' => $criteria->getAttributes())); } } $success = true; } else { $success = false; } // Commit the transaction regardless of whether we saved the section, in case something changed // in onBeforeSaveSection if ($transaction !== null) { $transaction->commit(); } } catch (\Exception $e) { if ($transaction !== null) { $transaction->rollback(); } throw $e; } } else { $success = false; } if ($success) { // Fire an 'onSaveSection' event $this->onSaveSection(new Event($this, array('section' => $section, 'isNewSection' => $isNewSection))); } return $success; }
/** * @inheritDoc IElementType::getIndexHtml() * * @param ElementCriteriaModel $criteria * @param array $disabledElementIds * @param array $viewState * @param null|string $sourceKey * @param null|string $context * @param bool $includeContainer * @param bool $showCheckboxes * * @return string */ public function getIndexHtml($criteria, $disabledElementIds, $viewState, $sourceKey, $context, $includeContainer, $showCheckboxes) { $variables = array('viewMode' => $viewState['mode'], 'context' => $context, 'elementType' => new ElementTypeVariable($this), 'disabledElementIds' => $disabledElementIds, 'collapsedElementIds' => craft()->request->getParam('collapsedElementIds'), 'showCheckboxes' => $showCheckboxes); // Special case for sorting by structure if (isset($viewState['order']) && $viewState['order'] == 'structure') { $source = $this->getSource($sourceKey, $context); if (isset($source['structureId'])) { $criteria->order = 'lft asc'; $variables['structure'] = craft()->structures->getStructureById($source['structureId']); // Are they allowed to make changes to this structure? if ($context == 'index' && $variables['structure'] && !empty($source['structureEditable'])) { $variables['structureEditable'] = true; // Let StructuresController know that this user can make changes to the structure craft()->userSession->authorize('editStructure:' . $variables['structure']->id); } } else { unset($viewState['order']); } } else { if (!empty($viewState['order']) && $viewState['order'] == 'score') { $criteria->order = 'score'; } else { $sortableAttributes = $this->defineSortableAttributes(); if ($sortableAttributes) { $order = !empty($viewState['order']) && isset($sortableAttributes[$viewState['order']]) ? $viewState['order'] : ArrayHelper::getFirstKey($sortableAttributes); $sort = !empty($viewState['sort']) && in_array($viewState['sort'], array('asc', 'desc')) ? $viewState['sort'] : 'asc'; // Combine them, accounting for the possibility that $order could contain multiple values, // and be defensive about the possibility that the first value actually has "asc" or "desc" // typeId => typeId [sort] // typeId, title => typeId [sort], title // typeId, title desc => typeId [sort], title desc // typeId desc => typeId [sort] $criteria->order = preg_replace('/^(.*?)(?:\\s+(?:asc|desc))?(,.*)?$/i', "\$1 {$sort}\$2", $order); } } } switch ($viewState['mode']) { case 'table': // Get the table columns $variables['attributes'] = $this->getTableAttributesForSource($sourceKey); // Give each attribute a chance to modify the criteria foreach ($variables['attributes'] as $attribute) { $this->prepElementCriteriaForTableAttribute($criteria, $attribute[0]); } break; } $variables['elements'] = $criteria->find(); $template = '_elements/' . $viewState['mode'] . 'view/' . ($includeContainer ? 'container' : 'elements'); return craft()->templates->render($template, $variables); }