Beispiel #1
0
 public function testSetupWithRecord()
 {
     $app = $this->getApp();
     $content = new Content($app, 'pages');
     $content->setValue('id', 5);
     $event = new StorageEvent($content);
     $this->assertEquals(5, $event->getId());
     $this->assertEquals('pages', $event->getContentType());
 }
Beispiel #2
0
 public function testgetValues()
 {
     $app = $this->getApp();
     $content = new Content($app, 'pages');
     $content->setValue('title', 'Test Page');
     $content->setValue('image', array('file' => 'image1.jpg', 'title' => 'Test image'));
     $values = $content->getValues(true);
     $this->assertEquals('Test Page', $values['title']);
     $this->assertEquals('{"file":"image1.jpg","title":"Test image"}', $values['image']);
 }
 public function testDefaultCode()
 {
     $entry = new Content($this->app, 'entries');
     $entry->setValue('title', 'Test');
     $entry->setValue('slug', 'test-default-code');
     $entry->setValue('ownerid', 1);
     $entry->setValue('status', 'published');
     $id = $this->app['storage']->saveContent($entry);
     $values = ['source' => '/test-default-code', 'contentId' => $id, 'contentType' => 'entries', 'code' => null];
     $redirect = new Redirect($values);
     $redirect->save();
     $request = Request::create('/test-default-code');
     $response = $this->app->handle($request);
     $default = $this->extension->config['default_status_code'];
     $default = empty($default) ? 302 : $default;
     $this->assertEquals($response->getStatusCode(), $default);
 }
Beispiel #4
0
 /**
  * Check if a given name is a valid column, and if it can be used in queries.
  *
  * @param  string $name
  * @param  array $contenttype
  * @param  bool $allowVariants
  * @return bool
  */
 private function isValidColumn($name, $contenttype, $allowVariants = false)
 {
     // Strip the minus in '-title' if allowed..
     if ($allowVariants) {
         if (strlen($name) > 0 && $name[0] == "-") {
             $name = substr($name, 1);
         }
         $name = $this->getFieldName($name);
     }
     // Check if the $name is in the contenttype's fields.
     if (isset($contenttype['fields'][$name])) {
         return true;
     }
     if (in_array($name, Content::getBaseColumns())) {
         return true;
     }
     return false;
 }
Beispiel #5
0
 /**
  * Create a list of fields types used in regular, template and virtual fields.
  *
  * @param array   $contenttype
  * @param Content $content
  * @param array   $has
  *
  * @return array
  */
 private function getUsedFieldtypes(array $contenttype, Content $content, array $has)
 {
     $fieldtypes = ['meta' => true];
     foreach ([$contenttype['fields'], $content->get('templatefields')->contenttype['fields'] ?: []] as $fields) {
         foreach ($fields as $field) {
             $fieldtypes[$field['type']] = true;
         }
     }
     if ($has['relations'] || $has['incoming_relations']) {
         $fieldtypes['relationship'] = true;
     }
     if ($has['taxonomy'] || is_array($contenttype['groups']) && in_array('taxonomy', $contenttype['groups'])) {
         $fieldtypes['taxonomy'] = true;
     }
     if ($has['templatefields'] || is_array($contenttype['groups']) && in_array('template', $contenttype['groups'])) {
         $fieldtypes['template'] = true;
     }
     return array_keys($fieldtypes);
 }
Beispiel #6
0
 /**
  * Update a Bolt contenttype record.
  *
  * @param \Bolt\Content $content The content object to be updated
  * @param string        $comment Add a comment to save with change.
  *
  * @throws \Bolt\Exception\StorageException
  *
  * @return bool
  */
 private function updateContent(Bolt\Content $content, $comment = null)
 {
     $tablename = $this->getContenttypeTablename($content->contenttype);
     // Set the date the record was changed
     $content->setValue('datechanged', date('Y-m-d H:i:s'));
     // Test that the record exists in the database
     $oldContent = $this->findContent($tablename, $content['id']);
     if (empty($oldContent)) {
         throw new StorageException('Attempted to update a non-existent record');
     }
     // Get the JSON database prepared values and make sure it's valid
     $fieldvalues = $this->getValidSaveData($content->getValues(true), $content->contenttype);
     // Do the actual update, and log it.
     $res = $this->app['db']->update($tablename, $fieldvalues, array('id' => $content['id']));
     if ($res > 0) {
         $this->logUpdate($content->contenttype['slug'], $content['id'], $fieldvalues, $oldContent, $comment);
         return true;
     }
 }
Beispiel #7
0
 /**
  * Set a Contenttype record's individual value.
  *
  * @param string $key
  * @param mixed  $value
  */
 public function setValue($key, $value)
 {
     // Don't set templateFields if not a real contenttype
     if ($key === 'templatefields' && !$this->isRootType) {
         return;
     }
     // Check if the value need to be unserialized.
     if (is_string($value) && substr($value, 0, 2) === "a:") {
         try {
             $unserdata = Lib::smartUnserialize($value);
         } catch (\Exception $e) {
             $unserdata = false;
         }
         if ($unserdata !== false) {
             $value = $unserdata;
         }
     }
     if ($key == 'id') {
         $this->id = $value;
     }
     // Set the user in the object.
     if ($key === 'ownerid' && !empty($value)) {
         $this->user = $this->app['users']->getUser($value);
     }
     // Only set values if they have are actually a field.
     $allowedcolumns = self::getBaseColumns();
     $allowedcolumns[] = 'taxonomy';
     if (!isset($this->contenttype['fields'][$key]) && !in_array($key, $allowedcolumns)) {
         return;
     }
     if (in_array($key, ['datecreated', 'datechanged', 'datepublish', 'datedepublish'])) {
         if (!preg_match("/(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/", $value)) {
             // @todo Try better date-parsing, instead of just setting it to
             // 'now' (or 'the past' for datedepublish)
             if ($key == 'datedepublish') {
                 $value = null;
             } else {
                 $value = date('Y-m-d H:i:s');
             }
         }
     }
     if ($key === 'templatefields') {
         if (is_string($value) || is_array($value)) {
             if (is_string($value)) {
                 try {
                     $unserdata = Lib::smartUnserialize($value);
                 } catch (\Exception $e) {
                     $unserdata = false;
                 }
             } else {
                 $unserdata = $value;
             }
             if (is_array($unserdata)) {
                 $templateContent = new Content($this->app, $this->getTemplateFieldsContentType(), [], false);
                 $value = $templateContent;
                 $this->populateTemplateFieldsContenttype($value);
                 $templateContent->setValues($unserdata);
             } else {
                 $value = null;
             }
         }
     }
     if (!isset($this->values['datechanged']) || !preg_match("/(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/", $this->values['datechanged'])) {
         $this->values['datechanged'] = date("Y-m-d H:i:s");
     }
     $this->values[$key] = $value;
 }
Beispiel #8
0
 /**
  * Returns all field names for the given contenttype.
  *
  * @param string $contenttype The name of the contenttype.
  * @return string[] An array with all field definitions for the given
  *                  contenttype. This includes the base columns as well.
  */
 private function getAllFieldNames($contenttype)
 {
     $baseFields = \Bolt\Content::getBaseColumns();
     $definedFields = $this->app['config']->get("contenttypes/{$contenttype}/fields", []);
     $taxonomyFields = $this->getAllTaxonomies($contenttype);
     // Fields could be empty, although it's a rare case.
     if (!empty($definedFields)) {
         $definedFields = array_keys($definedFields);
     }
     $definedFields = array_merge($definedFields, $taxonomyFields);
     return array_merge($baseFields, $definedFields);
 }
 protected function write(array $record)
 {
     // Simply exit if we're not enabled
     if (!$this->app['config']->get('general/changelog/enabled')) {
         return;
     }
     // Initialise ourselves if not already
     if (!$this->initialized) {
         $this->initialize();
     }
     // Check for a valid call
     if (!in_array($record['context']['action'], $this->allowed)) {
         throw new \Exception("Invalid action '{$record['context']['action']}' specified for changelog (must be one of [ " . implode(', ', $this->allowed) . " ])");
     }
     if (empty($record['context']['old']) && empty($record['context']['new'])) {
         throw new \Exception("Tried to log something that cannot be: both old and new content are empty");
     }
     if (empty($record['context']['old']) && in_array($record['context']['action'], ['UPDATE', 'DELETE'])) {
         throw new \Exception("Cannot log action '{$record['context']['action']}' when old content doesn't exist");
     }
     if (empty($record['context']['new']) && in_array($record['context']['action'], ['INSERT', 'UPDATE'])) {
         throw new \Exception("Cannot log action '{$record['context']['action']}' when new content is empty");
     }
     $data = [];
     switch ($record['context']['action']) {
         case 'UPDATE':
             $diff = DeepDiff::diff($record['context']['old'], $record['context']['new']);
             foreach ($diff as $item) {
                 list($k, $old, $new) = $item;
                 if (isset($record['context']['new'][$k])) {
                     $data[$k] = [$old, $new];
                 }
             }
             break;
         case 'INSERT':
             foreach ($record['context']['new'] as $k => $val) {
                 $data[$k] = [null, $val];
             }
             break;
         case 'DELETE':
             foreach ($record['context']['old'] as $k => $val) {
                 $data[$k] = [$val, null];
             }
             break;
     }
     if ($record['context']['new']) {
         $content = new Content($this->app, $record['context']['contenttype'], $record['context']['new']);
     } else {
         $content = new Content($this->app, $record['context']['contenttype'], $record['context']['old']);
     }
     $title = $content->getTitle();
     if (empty($title)) {
         /** @var \Bolt\Content $content */
         $content = $this->app['storage']->getContent($record['context']['contenttype'] . '/' . $record['context']['id']);
         $title = $content->getTitle();
     }
     // Don't store datechanged, or records that are only datechanged
     unset($data['datechanged']);
     if (empty($data)) {
         return;
     }
     $str = json_encode($data);
     $user = $this->app['users']->getCurrentUser();
     try {
         $this->app['db']->insert($this->tablename, ['date' => $record['datetime']->format('Y-m-d H:i:s'), 'ownerid' => $user['id'], 'title' => $title, 'contenttype' => $record['context']['contenttype'], 'contentid' => $record['context']['id'], 'mutation_type' => $record['context']['action'], 'diff' => $str, 'comment' => $record['context']['comment']]);
     } catch (\Exception $e) {
         // Nothing.
     }
 }
 /**
  * Compare by search weights.
  *
  * Or fallback to dates or title
  *
  * @param \Bolt\Content $a
  * @param \Bolt\Content $b
  *
  * @return int
  */
 private function compareSearchWeights(\Bolt\Content $a, \Bolt\Content $b)
 {
     if ($a->getSearchResultWeight() > $b->getSearchResultWeight()) {
         return -1;
     }
     if ($a->getSearchResultWeight() < $b->getSearchResultWeight()) {
         return 1;
     }
     if ($a['datepublish'] > $b['datepublish']) {
         // later is more important
         return -1;
     }
     if ($a['datepublish'] < $b['datepublish']) {
         // earlier is less important
         return 1;
     }
     return strcasecmp($a['title'], $b['title']);
 }
Beispiel #11
0
 public function getEmptyContent($contenttypeslug)
 {
     $contenttype = $this->getContentType($contenttypeslug);
     $content = new Bolt\Content('', $contenttypeslug);
     $values = array('id' => '', 'slug' => '', 'datecreated' => '', 'datechanged' => '', 'datepublish' => '', 'username' => '', 'status' => '');
     foreach ($contenttype['fields'] as $key => $field) {
         $values[$key] = '';
         // Set the default values.
         if (isset($field['default'])) {
             $values[$key] = $field['default'];
         } else {
             $values[$key] = '';
         }
     }
     $content->setValues($values);
     // echo "<pre>\n" . util::var_dump($content, true) . "</pre>\n";
     return $content;
 }
Beispiel #12
0
 /**
  * Check whether the status is allowed.
  *
  * We act as if a status *transition* were requested and fallback to the old
  * status otherwise.
  *
  * @param Application $app
  * @param Content     $content
  * @param string      $contentTypeSlug
  * @param integer     $id
  * @param string      $oldStatus
  */
 private function setTransitionStatus(Application $app, Content $content, $contentTypeSlug, $id, $oldStatus)
 {
     $canTransition = $app['users']->isContentStatusTransitionAllowed($oldStatus, $content['status'], $contentTypeSlug, $id);
     if (!$canTransition) {
         $content->setValue('status', $oldStatus);
     }
 }
Beispiel #13
0
 /**
  * Determine which templates will result in templatefields.
  *
  * @param array   $contenttype
  * @param Content $content
  *
  * @return array
  */
 private function getTempateFieldTemplates(array $contenttype, Content $content)
 {
     $templateFieldTemplates = [];
     if ($templateFieldsConfig = $this->app['config']->get('theme/templatefields')) {
         $templateFieldTemplates = array_keys($templateFieldsConfig);
         // Special case for default template
         $toRepair = [];
         foreach ($contenttype['fields'] as $name => $field) {
             if ($field['type'] === 'templateselect' && !empty($content->values[$name])) {
                 $toRepair[$name] = $content->values[$name];
                 $content->setValue($name, '');
             }
         }
         if ($content->hasTemplateFields()) {
             $templateFieldTemplates[] = '';
         }
         foreach ($toRepair as $name => $value) {
             $content->setValue($name, $value);
         }
     }
     return $templateFieldTemplates;
 }
 /**
  * Create the prototype context based on the parent.
  *
  * @param array $context
  * @param string $key
  *
  * @return array
  */
 public function getPrototypeContext(array $context, $key)
 {
     list($fields, $groups) = $this->wrapParseFieldsAndGroups($context['contenttype']['fields'][$key]['children']);
     foreach ($fields as $childKey => &$value) {
         list($realName, $realId) = $this->getRealNameAndId($key, $childKey);
         $value['real_name'] = $realName;
         $value['real_id'] = $realId;
     }
     // Do content.
     $content = new Content($this->app, '', array());
     foreach ($fields as $key => $options) {
         $content->setValue($key, $options['default']);
     }
     // Remove btn.
     list(, $realBtnId) = $this->getRealNameAndId($key, 'array_item_remove_btn');
     $childrenContext = array('contenttype' => array('fields' => $fields), 'content' => $content, 'allowed_status' => $context['allowed_status'], 'contentowner' => $context['contentowner'], 'fields' => $context['fields'], 'fieldtemplates' => $context['fieldtemplates'], 'can_upload' => $context['can_upload'], 'groups' => $groups ?: array('ungrouped' => array_keys($fields)), 'has' => array('incoming_relations' => false, 'relations' => false, 'tabs' => false, 'taxonomy' => false, 'templatefields' => false), 'array_options' => array('btn_remove_id' => $realBtnId));
     return $childrenContext;
 }