/**
  * Handle the onBeforeSaveEntry event.
  *
  * @param Event $event
  */
 public function onBeforeSaveEntry(Event $event)
 {
     // Get entry id to save
     $id = $event->params['entry']->id;
     if (!$event->params['isNewEntry']) {
         // Get old entry from db
         $entry = EntryModel::populateModel(EntryRecord::model()->findById($id));
         // Get fields
         $this->before = $this->fields($entry);
     } else {
         // Get fields
         $this->before = $this->fields($event->params['entry'], true);
     }
 }
 /**
  * Saves an entry.
  *
  * @param EntryModel $entry
  * @throws Exception
  * @return bool
  */
 public function saveEntry(EntryModel $entry)
 {
     $isNewEntry = !$entry->id;
     // Entry data
     if (!$isNewEntry) {
         $entryRecord = EntryRecord::model()->with('element')->findById($entry->id);
         if (!$entryRecord) {
             throw new Exception(Craft::t('No entry exists with the ID “{id}”', array('id' => $entry->id)));
         }
         $elementRecord = $entryRecord->element;
         // if entry->sectionId is null and there is an entryRecord sectionId, we assume this is a front-end edit.
         if ($entry->sectionId === null && $entryRecord->sectionId) {
             $entry->sectionId = $entryRecord->sectionId;
         }
     } else {
         $entryRecord = new EntryRecord();
         $elementRecord = new ElementRecord();
         $elementRecord->type = ElementType::Entry;
     }
     $section = craft()->sections->getSectionById($entry->sectionId);
     if (!$section) {
         throw new Exception(Craft::t('No section exists with the ID “{id}”', array('id' => $entry->sectionId)));
     }
     $sectionLocales = $section->getLocales();
     if (!isset($sectionLocales[$entry->locale])) {
         throw new Exception(Craft::t('The section “{section}” is not enabled for the locale {locale}', array('section' => $section->name, 'locale' => $entry->locale)));
     }
     $entryRecord->sectionId = $entry->sectionId;
     $entryRecord->authorId = $entry->authorId;
     $entryRecord->postDate = $entry->postDate;
     $entryRecord->expiryDate = $entry->expiryDate;
     if ($entry->enabled && !$entryRecord->postDate) {
         // Default the post date to the current date/time
         $entryRecord->postDate = $entry->postDate = DateTimeHelper::currentUTCDateTime();
     }
     $entryRecord->validate();
     $entry->addErrors($entryRecord->getErrors());
     $elementRecord->enabled = $entry->enabled;
     $elementRecord->validate();
     $entry->addErrors($elementRecord->getErrors());
     // Entry locale data
     if ($entry->id) {
         $entryLocaleRecord = EntryLocaleRecord::model()->findByAttributes(array('entryId' => $entry->id, 'locale' => $entry->locale));
         // If entry->slug is null and there is an entryLocaleRecord slug, we assume this is a front-end edit.
         if ($entry->slug === null && $entryLocaleRecord->slug) {
             $entry->slug = $entryLocaleRecord->slug;
         }
     }
     if (empty($entryLocaleRecord)) {
         $entryLocaleRecord = new EntryLocaleRecord();
         $entryLocaleRecord->sectionId = $entry->sectionId;
         $entryLocaleRecord->locale = $entry->locale;
     }
     if ($entryLocaleRecord->isNewRecord() || $entry->slug != $entryLocaleRecord->slug) {
         $this->_generateEntrySlug($entry);
         $entryLocaleRecord->slug = $entry->slug;
     }
     $entryLocaleRecord->validate();
     $entry->addErrors($entryLocaleRecord->getErrors());
     // Element locale data
     if ($entry->id) {
         $elementLocaleRecord = ElementLocaleRecord::model()->findByAttributes(array('elementId' => $entry->id, 'locale' => $entry->locale));
     }
     if (empty($elementLocaleRecord)) {
         $elementLocaleRecord = new ElementLocaleRecord();
         $elementLocaleRecord->locale = $entry->locale;
     }
     if ($section->hasUrls && $entry->enabled) {
         // Make sure the section's URL format is valid. This shouldn't be possible due to section validation,
         // but it's not enforced by the DB, so anything is possible.
         $urlFormat = $sectionLocales[$entry->locale]->urlFormat;
         if (!$urlFormat || strpos($urlFormat, '{slug}') === false) {
             throw new Exception(Craft::t('The section “{section}” doesn’t have a valid URL Format.', array('section' => Craft::t($section->name))));
         }
         $elementLocaleRecord->uri = craft()->templates->renderObjectTemplate($urlFormat, $entry);
     } else {
         $elementLocaleRecord->uri = null;
     }
     $elementLocaleRecord->validate();
     $entry->addErrors($elementLocaleRecord->getErrors());
     // Entry content
     $fieldLayout = $section->getFieldLayout();
     $content = craft()->content->prepElementContentForSave($entry, $fieldLayout);
     $content->validate();
     $entry->addErrors($content->getErrors());
     if (!$entry->hasErrors()) {
         // Save the element record first
         $elementRecord->save(false);
         // Now that we have an element ID, save it on the other stuff
         if (!$entry->id) {
             $entry->id = $elementRecord->id;
             $entryRecord->id = $entry->id;
         }
         $entryRecord->save(false);
         $entryLocaleRecord->entryId = $entry->id;
         $elementLocaleRecord->elementId = $entry->id;
         $content->elementId = $entry->id;
         // Save the other records
         $entryLocaleRecord->save(false);
         $elementLocaleRecord->save(false);
         craft()->content->saveContent($content, false);
         // Update the search index
         craft()->search->indexElementAttributes($entry, $entry->locale);
         // Save a new version
         if (Craft::hasPackage(CraftPackage::PublishPro)) {
             craft()->entryRevisions->saveVersion($entry);
         }
         // Perform some post-save operations
         craft()->content->postSaveOperations($entry, $content);
         // Fire an 'onSaveEntry' event
         $this->onSaveEntry(new Event($this, array('entry' => $entry, 'isNewEntry' => $isNewEntry)));
         return true;
     } else {
         return false;
     }
 }
 /**
  * Saves a new or existing entry.
  *
  * ```php
  * $entry = new EntryModel();
  * $entry->sectionId = 10;
  * $entry->typeId    = 1;
  * $entry->authorId  = 5;
  * $entry->enabled   = true;
  *
  * $entry->getContent()->title = "Hello World!";
  *
  * $entry->setContentFromPost(array(
  *     'body' => "<p>I can’t believe I literally just called this “Hello World!”.</p>",
  * ));
  *
  * $success = craft()->entries->saveEntry($entry);
  *
  * if (!$success)
  * {
  *     Craft::log('Couldn’t save the entry "'.$entry->title.'"', LogLevel::Error);
  * }
  * ```
  *
  * @param EntryModel $entry The entry to be saved.
  *
  * @throws \Exception
  * @return bool Whether the entry was saved successfully.
  */
 public function saveEntry(EntryModel $entry)
 {
     $isNewEntry = !$entry->id;
     $hasNewParent = $this->_checkForNewParent($entry);
     if ($hasNewParent) {
         if ($entry->parentId) {
             $parentEntry = $this->getEntryById($entry->parentId, $entry->locale);
             if (!$parentEntry) {
                 throw new Exception(Craft::t('No entry exists with the ID “{id}”.', array('id' => $entry->parentId)));
             }
         } else {
             $parentEntry = null;
         }
         $entry->setParent($parentEntry);
     }
     // Get the entry record
     if (!$isNewEntry) {
         $entryRecord = EntryRecord::model()->findById($entry->id);
         if (!$entryRecord) {
             throw new Exception(Craft::t('No entry exists with the ID “{id}”.', array('id' => $entry->id)));
         }
     } else {
         $entryRecord = new EntryRecord();
     }
     // Get the section
     $section = craft()->sections->getSectionById($entry->sectionId);
     if (!$section) {
         throw new Exception(Craft::t('No section exists with the ID “{id}”.', array('id' => $entry->sectionId)));
     }
     // Verify that the section is available in this locale
     $sectionLocales = $section->getLocales();
     if (!isset($sectionLocales[$entry->locale])) {
         throw new Exception(Craft::t('The section “{section}” is not enabled for the locale {locale}', array('section' => $section->name, 'locale' => $entry->locale)));
     }
     // Set the entry data
     $entryType = $entry->getType();
     $entryRecord->sectionId = $entry->sectionId;
     if ($section->type == SectionType::Single) {
         $entryRecord->authorId = $entry->authorId = null;
         $entryRecord->expiryDate = $entry->expiryDate = null;
     } else {
         $entryRecord->authorId = $entry->authorId;
         $entryRecord->postDate = $entry->postDate;
         $entryRecord->expiryDate = $entry->expiryDate;
         $entryRecord->typeId = $entryType->id;
     }
     if ($entry->enabled && !$entryRecord->postDate) {
         // Default the post date to the current date/time
         $entryRecord->postDate = $entry->postDate = DateTimeHelper::currentUTCDateTime();
     }
     $entryRecord->validate();
     $entry->addErrors($entryRecord->getErrors());
     if ($entry->hasErrors()) {
         return false;
     }
     if (!$entryType->hasTitleField) {
         $entry->getContent()->title = craft()->templates->renderObjectTemplate($entryType->titleFormat, $entry);
     }
     $transaction = craft()->db->getCurrentTransaction() === null ? craft()->db->beginTransaction() : null;
     try {
         // Fire an 'onBeforeSaveEntry' event
         $event = new Event($this, array('entry' => $entry, 'isNewEntry' => $isNewEntry));
         $this->onBeforeSaveEntry($event);
         // Is the event giving us the go-ahead?
         if ($event->performAction) {
             // Save the element
             $success = craft()->elements->saveElement($entry);
             // If it didn't work, rollback the transaction in case something changed in onBeforeSaveEntry
             if (!$success) {
                 if ($transaction !== null) {
                     $transaction->rollback();
                 }
                 // If "title" has an error, check if they've defined a custom title label.
                 if ($entry->getError('title')) {
                     // Grab all of the original errors.
                     $errors = $entry->getErrors();
                     // Grab just the title error message.
                     $originalTitleError = $errors['title'];
                     // Clear the old.
                     $entry->clearErrors();
                     // Create the new "title" error message.
                     $errors['title'] = str_replace('Title', $entryType->titleLabel, $originalTitleError);
                     // Add all of the errors back on the model.
                     $entry->addErrors($errors);
                 }
                 return false;
             }
             // Now that we have an element ID, save it on the other stuff
             if ($isNewEntry) {
                 $entryRecord->id = $entry->id;
             }
             // Save the actual entry row
             $entryRecord->save(false);
             if ($section->type == SectionType::Structure) {
                 // Has the parent changed?
                 if ($hasNewParent) {
                     if (!$entry->parentId) {
                         craft()->structures->appendToRoot($section->structureId, $entry);
                     } else {
                         craft()->structures->append($section->structureId, $entry, $parentEntry);
                     }
                 }
                 // Update the entry's descendants, who may be using this entry's URI in their own URIs
                 craft()->elements->updateDescendantSlugsAndUris($entry);
             }
             // Save a new version
             if (craft()->getEdition() >= Craft::Client && $section->enableVersioning) {
                 craft()->entryRevisions->saveVersion($entry);
             }
         } else {
             $success = false;
         }
         // Commit the transaction regardless of whether we saved the entry, in case something changed
         // in onBeforeSaveEntry
         if ($transaction !== null) {
             $transaction->commit();
         }
     } catch (\Exception $e) {
         if ($transaction !== null) {
             $transaction->rollback();
         }
         throw $e;
     }
     if ($success) {
         // Fire an 'onSaveEntry' event
         $this->onSaveEntry(new Event($this, array('entry' => $entry, 'isNewEntry' => $isNewEntry)));
     }
     return $success;
 }
 /**
  * Initialize the category saving/deleting events.
  */
 public function log()
 {
     // Get values before saving
     craft()->on('entries.onBeforeSaveEntry', function (Event $event) {
         // Get entry id to save
         $id = $event->params['entry']->id;
         if (!$event->params['isNewEntry']) {
             // Get old entry from db
             $entry = EntryModel::populateModel(EntryRecord::model()->findById($id));
             // Get fields
             craft()->auditLog_entry->before = craft()->auditLog_entry->fields($entry);
         } else {
             // Get fields
             craft()->auditLog_entry->before = craft()->auditLog_entry->fields($event->params['entry'], true);
         }
     });
     // Get values after saving
     craft()->on('entries.onSaveEntry', function (Event $event) {
         // Get saved entry
         $entry = $event->params['entry'];
         // Get fields
         craft()->auditLog_entry->after = craft()->auditLog_entry->fields($entry);
         // New row
         $log = new AuditLogRecord();
         // Get user
         $user = craft()->userSession->getUser();
         // Set user id
         $log->userId = $user ? $user->id : null;
         // Set element type
         $log->type = ElementType::Entry;
         // Set origin
         $log->origin = craft()->request->isCpRequest() ? craft()->config->get('cpTrigger') . '/' . craft()->request->path : craft()->request->path;
         // Set before
         $log->before = craft()->auditLog_entry->before;
         // Set after
         $log->after = craft()->auditLog_entry->after;
         // Set status
         $log->status = $event->params['isNewEntry'] ? AuditLogModel::CREATED : AuditLogModel::MODIFIED;
         // Save row
         $log->save(false);
         // Callback
         craft()->auditLog->elementHasChanged(ElementType::Entry, $entry->id, craft()->auditLog_entry->before, craft()->auditLog_entry->after);
     });
     // Get values before deleting
     craft()->on('entries.onBeforeDeleteEntry', function (Event $event) {
         // Get deleted entry
         $entry = $event->params['entry'];
         // Get fields
         craft()->auditLog_entry->before = craft()->auditLog_entry->fields($entry);
         craft()->auditLog_entry->after = craft()->auditLog_entry->fields($entry, true);
         // New row
         $log = new AuditLogRecord();
         // Set user id
         $log->userId = craft()->userSession->getUser()->id;
         // Set element type
         $log->type = ElementType::Entry;
         // Set origin
         $log->origin = craft()->request->isCpRequest() ? craft()->config->get('cpTrigger') . '/' . craft()->request->path : craft()->request->path;
         // Set before
         $log->before = craft()->auditLog_entry->before;
         // Set after
         $log->after = craft()->auditLog_entry->after;
         // Set status
         $log->status = AuditLogModel::DELETED;
         // Save row
         $log->save(false);
         // Callback
         craft()->auditLog->elementHasChanged(ElementType::Entry, $entry->id, craft()->auditLog_entry->before, craft()->auditLog_entry->after);
     });
 }