/**
  * Save the sortfield for a given Page
  *
  * @param Page
  * @return bool
  *
  */
 public function save(Page $page)
 {
     if (!$page->id) {
         return;
     }
     if (!$page->isChanged('sortfield')) {
         return;
     }
     $sortfield = $this->fuel('db')->escape_string($this->encode($page->sortfield));
     if ($sortfield == 'sort' || !$sortfield) {
         return $this->delete($page);
     }
     $sql = "INSERT INTO pages_sortfields (pages_id, sortfield) " . "VALUES({$page->id}, '{$sortfield}') " . "ON DUPLICATE KEY UPDATE sortfield=VALUES(sortfield)";
     return $this->fuel('db')->query($sql) != false;
 }
 /**
  * Save the sortfield for a given Page
  *
  * @param Page
  * @return bool
  *
  */
 public function save(Page $page)
 {
     if (!$page->id) {
         return false;
     }
     if (!$page->isChanged('sortfield')) {
         return true;
     }
     $page_id = (int) $page->id;
     $database = $this->wire('database');
     $sortfield = $this->encode($page->sortfield);
     if ($sortfield == 'sort' || !$sortfield) {
         return $this->delete($page);
     }
     $sql = "INSERT INTO pages_sortfields (pages_id, sortfield) " . "VALUES(:page_id, :sortfield) " . "ON DUPLICATE KEY UPDATE sortfield=VALUES(sortfield)";
     $query = $database->prepare($sql);
     $query->bindValue(":page_id", $page_id, PDO::PARAM_INT);
     $query->bindValue(":sortfield", $sortfield, PDO::PARAM_STR);
     $result = $query->execute();
     return $result;
 }
 function testIsChanged()
 {
     $page = $this->objFromFixture('Page', 'home');
     $page->Title = 'Home-Changed';
     $page->ShowInMenus = true;
     // type change only, database stores "1"
     $this->assertTrue($page->isChanged('Title', 1));
     $this->assertTrue($page->isChanged('Title', 2));
     $this->assertTrue($page->isChanged('ShowInMenus', 1));
     $this->assertFalse($page->isChanged('ShowInMenus', 2));
     $this->assertFalse($page->isChanged('Content', 1));
     $this->assertFalse($page->isChanged('Content', 2));
     $newPage = new Page();
     $newPage->Title = "New Page Title";
     $this->assertTrue($newPage->isChanged('Title', 1));
     $this->assertTrue($newPage->isChanged('Title', 2));
     $this->assertFalse($newPage->isChanged('Content', 1));
     $this->assertFalse($newPage->isChanged('Content', 2));
     $newPage->write();
     $this->assertFalse($newPage->isChanged('Title', 1));
     $this->assertFalse($newPage->isChanged('Title', 2));
     $this->assertFalse($newPage->isChanged('Content', 1));
     $this->assertFalse($newPage->isChanged('Content', 2));
     $page = $this->objFromFixture('Page', 'home');
     $page->Title = null;
     $this->assertTrue($page->isChanged('Title', 1));
     $this->assertTrue($page->isChanged('Title', 2));
     /* Test when there's not field provided */
     $page = $this->objFromFixture('Page', 'home');
     $page->Title = "New Page Title";
     $this->assertTrue($page->isChanged());
     $page->write();
     $this->assertFalse($page->isChanged());
 }
Example #4
0
 /**
  * Save the given field from page 
  *
  * Possible template method: If overridden, children should NOT call this parent method.
  *
  * @param Page $page Page object to save. 
  * @param Field $field Field to retrieve from the page. 
  * @return bool True on success, false on DB save failure.
  *
  */
 public function ___savePageField(Page $page, Field $field)
 {
     if (!$page->id) {
         throw new WireException("Unable to save to '{$field->table}' for page that doesn't exist in pages table");
     }
     if (!$field->id) {
         throw new WireException("Unable to save to '{$field->table}' for field that doesn't exist in fields table");
     }
     // if this field hasn't changed since it was loaded, don't bother executing the save
     if (!$page->isChanged($field->name)) {
         return true;
     }
     $value = $page->get($field->name);
     // if the value is the same as the default, then remove the field from the database because it's redundant
     if ($value === $this->getDefaultValue($page, $field)) {
         return $this->deletePageField($page, $field);
     }
     $value = $this->sleepValue($page, $field, $value);
     if (is_array($value)) {
         $sql1 = "INSERT INTO `{$field->table}` (pages_id";
         $sql2 = "VALUES('{$page->id}'";
         $sql3 = "ON DUPLICATE KEY UPDATE ";
         foreach ($value as $k => $v) {
             $sql1 .= ",{$k}";
             $sql2 .= ",'" . $this->db->escape_string($v) . "'";
             $sql3 .= "{$k}=VALUES({$k}), ";
         }
         $sql = "{$sql1}) {$sql2}) " . rtrim($sql3, ', ');
     } else {
         $value = $this->db->escape_string($value);
         $sql = "INSERT INTO `{$field->table}` (pages_id, data) " . "VALUES('{$page->id}', '{$value}') " . "ON DUPLICATE KEY UPDATE data=VALUES(data)";
     }
     $result = $this->db->query($sql);
     return $result;
 }
 /**
  * Per the Fieldtype interface, Save the given Field from the given Page to the database
  *
  * Because the number of values may have changed, this method plays it safe and deletes all the old values
  * and reinserts them as new. 
  *
  * @param Page $page
  * @param Field $field
  * @return bool
  * @throws WireException on failure
  *
  */
 public function ___savePageField(Page $page, Field $field)
 {
     if (!$page->id || !$field->id) {
         return false;
     }
     $database = $this->wire('database');
     $values = $page->get($field->name);
     $schema = array();
     if (is_object($values)) {
         if (!$values->isChanged() && !$page->isChanged($field->name)) {
             return true;
         }
     } else {
         if (!$page->isChanged($field->name)) {
             return true;
         }
     }
     $values = $this->sleepValue($page, $field, $values);
     $table = $database->escapeTable($field->table);
     $page_id = (int) $page->id;
     // since we don't manage IDs of existing values for multi fields, we delete the existing data and insert all of it again
     $query = $database->prepare("DELETE FROM `{$table}` WHERE pages_id=:page_id");
     // QA
     $query->bindValue(":page_id", $page_id, PDO::PARAM_INT);
     $query->execute();
     if (count($values)) {
         // get first value to find key definition
         $value = reset($values);
         // if the first value is not an associative (key indexed) array, then force it to be with 'data' as the key.
         // this is to allow for this method to be able to save fields that have more than just a 'data' field,
         // even though most instances will probably just use only the data field
         if (is_array($value)) {
             $keys = array_keys($value);
             foreach ($keys as $k => $v) {
                 $keys[$k] = $database->escapeTableCol($v);
             }
         } else {
             $keys = array('data');
         }
         $sql = "INSERT INTO `{$table}` (pages_id, sort, `" . implode('`, `', $keys) . "`) VALUES";
         $sort = 0;
         // cycle through the values to generate the query
         foreach ($values as $value) {
             $sql .= "({$page_id}, {$sort}, ";
             // if the value is not an associative array, then force it to be one
             if (!is_array($value)) {
                 $value = array('data' => $value);
             }
             // cycle through the keys, which represent DB fields (i.e. data, description, etc.) and generate the insert query
             foreach ($keys as $key) {
                 $v = isset($value[$key]) ? $value[$key] : null;
                 if (is_null($v)) {
                     if (empty($schema)) {
                         $schema = $this->getDatabaseSchema($field);
                     }
                     $sql .= isset($schema[$key]) && stripos($schema[$key], ' DEFAULT NULL') ? "NULL, " : "'', ";
                 } else {
                     $sql .= "'" . $database->escapeStr("{$v}") . "', ";
                 }
             }
             $sql = rtrim($sql, ", ") . "), ";
             $sort++;
         }
         $sql = rtrim($sql, ", ");
         $query = $database->prepare($sql);
         try {
             $result = $query->execute();
         } catch (Exception $e) {
             $msg = $e->getMessage();
             if ($this->wire('config')->debug && $this->wire('config')->advanced) {
                 $msg .= "\n{$sql}";
             }
             throw new WireException($msg);
         }
         return $result;
     }
     return true;
 }
 /**
  * Save the given field from page 
  *
  * Possible template method: If overridden, children should NOT call this parent method.
  *
  * @param Page $page Page object to save. 
  * @param Field $field Field to retrieve from the page. 
  * @return bool True on success, false on DB save failure.
  * @throws WireException
  *
  */
 public function ___savePageField(Page $page, Field $field)
 {
     if (!$page->id) {
         throw new WireException("Unable to save to '{$field->table}' for page that doesn't exist in pages table");
     }
     if (!$field->id) {
         throw new WireException("Unable to save to '{$field->table}' for field that doesn't exist in fields table");
     }
     // if this field hasn't changed since it was loaded, don't bother executing the save
     if (!$page->isChanged($field->name)) {
         return true;
     }
     $database = $this->wire('database');
     $value = $page->get($field->name);
     // if the value is the same as the default, then remove the field from the database because it's redundant
     if ($value === $this->getBlankValue($page, $field)) {
         return $this->deletePageField($page, $field);
     }
     $value = $this->sleepValue($page, $field, $value);
     $page_id = (int) $page->id;
     $table = $database->escapeTable($field->table);
     $schema = array();
     if (is_array($value)) {
         $sql1 = "INSERT INTO `{$table}` (pages_id";
         $sql2 = "VALUES('{$page_id}'";
         $sql3 = "ON DUPLICATE KEY UPDATE ";
         foreach ($value as $k => $v) {
             $k = $database->escapeCol($k);
             $sql1 .= ",`{$k}`";
             if (is_null($v)) {
                 // check if schema explicitly allows NULL
                 if (empty($schema)) {
                     $schema = $this->getDatabaseSchema($field);
                 }
                 $sql2 .= isset($schema[$k]) && stripos($schema[$k], ' DEFAULT NULL') ? ",NULL" : ",''";
             } else {
                 $v = $database->escapeStr($v);
                 $sql2 .= ",'{$v}'";
             }
             $sql3 .= "`{$k}`=VALUES(`{$k}`), ";
         }
         $sql = "{$sql1}) {$sql2}) " . rtrim($sql3, ', ');
     } else {
         if (is_null($value)) {
             // check if schema explicitly allows NULL
             $schema = $this->getDatabaseSchema($field);
             $value = isset($schema[$k]) && stripos($schema[$k], ' DEFAULT NULL') ? "NULL" : "''";
         } else {
             $value = "'" . $database->escapeStr($value) . "'";
         }
         $sql = "INSERT INTO `{$table}` (pages_id, data) " . "VALUES('{$page_id}', {$value}) " . "ON DUPLICATE KEY UPDATE data=VALUES(data)";
     }
     $query = $database->prepare($sql);
     $result = $query->execute();
     return $result;
 }
Example #7
0
 /**
  * Per the Fieldtype interface, Save the given Field from the given Page to the database
  *
  * Because the number of values may have changed, this method plays it safe and deletes all the old values
  * and reinserts them as new. 
  *
  * @param Page $page
  * @param Field $field
  * @return bool
  *
  */
 public function ___savePageField(Page $page, Field $field)
 {
     if (!$page->id || !$field->id) {
         return false;
     }
     $values = $page->get($field->name);
     // if(!$values) return false;
     /*
     if($this->config->debug) {
     	if($page->isChanged($field->name)) {
     		$this->message("Page {$page->id} reports that '{$field->name}' has changed");  
     	}
     	if($values->isChanged()) {
     		$this->message("Values changed for field: {$field->name}"); 
     		foreach($values->getChanges() as $key => $change) $this->message("{$field->name}: $key: $change"); 
     	}
     }
     */
     if (is_object($values)) {
         if (!$values->isChanged() && !$page->isChanged($field->name)) {
             return true;
         }
     } else {
         if (!$page->isChanged($field->name)) {
             return true;
         }
     }
     $values = $this->sleepValue($page, $field, $values);
     // since we don't manage IDs of existing values for multi fields, we delete the existing data and insert all of it again
     $this->db->query("DELETE FROM `{$field->table}` WHERE pages_id={$page->id}");
     if (count($values)) {
         // get first value to find key definition
         $value = reset($values);
         // if the first value is not an associative (key indexed) array, then force it to be with 'data' as the key.
         // this is to allow for this method to be able to save fields that have more than just a 'data' field,
         // even though most instances will probably just use only the data field
         if (is_array($value)) {
             $keys = array_keys($value);
         } else {
             $keys = array('data');
         }
         $sql = "INSERT INTO `{$field->table}` (pages_id, sort, " . implode(', ', $keys) . ") VALUES";
         $sort = 0;
         // cycle through the values to generate the query
         foreach ($values as $value) {
             $sql .= "({$page->id}, {$sort}, ";
             // if the value is not an associative array, then force it to be one
             if (!is_array($value)) {
                 $value = array('data' => $value);
             }
             // cycle through the keys, which represent DB fields (i.e. data, description, etc.) and generate the insert query
             foreach ($keys as $key) {
                 $v = $value[$key];
                 $sql .= "'" . $this->db->escape_string("{$v}") . "', ";
             }
             $sql = rtrim($sql, ", ") . "), ";
             $sort++;
         }
         $sql = rtrim($sql, ", ");
         $result = $this->db->query($sql);
         return $result;
     }
     return true;
 }
Example #8
0
 /**
  * Save individual Page fields and supporting actions
  * 
  * triggers hooks: saved, added, moved, renamed, templateChanged
  * 
  * @param Page $page
  * @param bool $isNew
  * @param array $options
  * @return bool
  * 
  */
 protected function savePageFinish(Page $page, $isNew, array $options)
 {
     $changes = $page->getChanges();
     $changesValues = $page->getChanges(true);
     // update children counts for current/previous parent
     if ($isNew) {
         $page->parent->numChildren++;
     } else {
         if ($page->parentPrevious && $page->parentPrevious->id != $page->parent->id) {
             $page->parentPrevious->numChildren--;
             $page->parent->numChildren++;
         }
     }
     // if page hasn't changed, don't continue further
     if (!$page->isChanged() && !$isNew) {
         $this->debugLog('save', '[not-changed]', true);
         $this->saved($page, array());
         return true;
     }
     // if page has a files path (or might have previously), trigger filesManager's save
     if (PagefilesManager::hasPath($page)) {
         $page->filesManager->save();
     }
     // disable outputFormatting and save state
     $of = $page->of();
     $page->of(false);
     // when a page is statusCorrupted, it records what fields are corrupted in _statusCorruptedFields array
     $corruptedFields = $page->hasStatus(Page::statusCorrupted) ? $page->_statusCorruptedFields : array();
     // save each individual Fieldtype data in the fields_* tables
     foreach ($page->fieldgroup as $field) {
         if (isset($corruptedFields[$field->name])) {
             continue;
         }
         // don't even attempt save of corrupted field
         if (!$field->type) {
             continue;
         }
         try {
             $field->type->savePageField($page, $field);
         } catch (Exception $e) {
             $error = sprintf($this->_('Error saving field "%s"'), $field->name) . ' - ' . $e->getMessage();
             $this->trackException($e, true, $error);
         }
     }
     // return outputFormatting state
     $page->of($of);
     if (empty($page->template->sortfield)) {
         $this->sortfields->save($page);
     }
     if ($options['resetTrackChanges']) {
         $page->resetTrackChanges();
     }
     // determine whether we'll trigger the added() hook
     if ($isNew) {
         $page->setIsNew(false);
         $triggerAddedPage = $page;
     } else {
         $triggerAddedPage = null;
     }
     // check for template changes
     if ($page->templatePrevious && $page->templatePrevious->id != $page->template->id) {
         // the template was changed, so we may have data in the DB that is no longer applicable
         // find unused data and delete it
         foreach ($page->templatePrevious->fieldgroup as $field) {
             if ($page->template->fieldgroup->has($field)) {
                 continue;
             }
             $field->type->deletePageField($page, $field);
             $this->message("Deleted field '{$field}' on page {$page->url}", Notice::debug);
         }
     }
     if ($options['uncacheAll']) {
         $this->uncacheAll($page);
     }
     // determine whether the pages_access table needs to be updated so that pages->find()
     // operations can be access controlled.
     if ($isNew || $page->parentPrevious || $page->templatePrevious) {
         new PagesAccess($page);
     }
     // lastly determine whether the pages_parents table needs to be updated for the find() cache
     // and call upon $this->saveParents where appropriate.
     if ($page->parentPrevious && $page->numChildren > 0) {
         // page is moved and it has children
         $this->saveParents($page->id, $page->numChildren);
         if ($page->parent->numChildren == 1) {
             $this->saveParents($page->parent_id, $page->parent->numChildren);
         }
     } else {
         if ($page->parentPrevious && $page->parent->numChildren == 1 || $isNew && $page->parent->numChildren == 1 || $page->forceSaveParents) {
             // page is moved and is the first child of it's new parent
             // OR page is NEW and is the first child of it's parent
             // OR $page->forceSaveParents is set (debug/debug, can be removed later)
             $this->saveParents($page->parent_id, $page->parent->numChildren);
         }
     }
     if ($page->parentPrevious && $page->parentPrevious->numChildren == 0) {
         // $page was moved and it's previous parent is now left with no children, this ensures the old entries get deleted
         $this->saveParents($page->parentPrevious->id, 0);
     }
     // trigger hooks
     $this->saved($page, $changes, $changesValues);
     if ($triggerAddedPage) {
         $this->added($triggerAddedPage);
     }
     if ($page->namePrevious && $page->namePrevious != $page->name) {
         $this->renamed($page);
     }
     if ($page->parentPrevious) {
         $this->moved($page);
     }
     if ($page->templatePrevious) {
         $this->templateChanged($page);
     }
     if (in_array('status', $changes)) {
         $this->statusChanged($page);
     }
     $this->debugLog('save', $page, true);
     return true;
 }