Created
August 26, 2014 06:51
-
-
Save mamchenkov/4ffd280451f47db01f6d to your computer and use it in GitHub Desktop.
Saving Article's draft in CakePHP 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* For this whole thing to work, you'll need at least these fields in your | |
* articles table: | |
* | |
* - id (article id) | |
* - parent_id (to link drafts to parent article) | |
* - slug (for friendly URLs usually) | |
* - title (obviously) | |
* - content (obviously) | |
* - status (published/draft/etc) | |
*/ | |
/* In the bootstrap.php */ | |
define('ARTICLE_STATUS_DRAFT', 'draft'); | |
/* In the Article model */ | |
/** | |
* beforeSave() callback | |
* | |
* Before we overwrite an existing article, fetch its original state and | |
* save it temporarily. We'll save it permanently in the afterSave(). | |
* | |
* @param array $options Options | |
* @return boolean True if we should proceed with save(), false otherwise. | |
*/ | |
public function beforeSave($options = array()) { | |
if (!empty($this->data['Article']['id'])) { | |
$article = $this->findById($this->data['Article']['id']); | |
$article['Article']['status'] = ARTICLE_STATUS_DRAFT; | |
$article['Article']['parent_id'] = $this->data['Article']['id']; | |
$article['Article']['id'] = null; | |
$this->draftData = $article; | |
} | |
return true; | |
} | |
/** | |
* afterSave() callback | |
* | |
* If we just saved a pre-existing record, grab the previous state of it | |
* and make a permanent copy | |
* | |
* @param boolean $created True if new record, false otherwise | |
* @param array $options Options | |
* @return void | |
*/ | |
public function afterSave($created, $options = Array()) { | |
if (!$created && !empty($this->draftData)) { | |
$newModel = clone $this; | |
$newModel->clear(); | |
$newModel->create(); | |
$newModel->save($this->draftData); | |
} | |
} | |
/* | |
* Get article drafts | |
* | |
* @param numeric $id ID of the article | |
* @param numeric $limit (Optionally) Limit on how many drafts to get | |
* @return array | |
*/ | |
public function getDrafts($id, $limit = 20) { | |
$result = $this->find('all', array( | |
'conditions' => array( | |
'Article.parent_id' => $id, | |
), | |
'order' => 'Article.id DESC', | |
'limit' => $limit, | |
)); | |
// If we haven't found any drafts, there is a possibility | |
// that we are looking at a draft currently. So we might | |
// try to fetch the siblings. | |
if (empty($result)) { | |
$article = $this->findById($id); | |
//Articles with no parent_id have no history or drafts | |
if ($article['Article']['parent_id'] !== null) { | |
$result = $this->find('all', array( | |
'conditions' => array( | |
'Article.parent_id' => $article['Article']['parent_id'], | |
'Article.id <>' => $id, | |
), | |
'order' => 'Article.id DESC', | |
'limit' => $limit, | |
)); | |
} | |
} | |
return $result; | |
} | |
/** | |
* Diff two given articles | |
* | |
* This requires the FineDiff library from: | |
* http://www.raymondhill.net/finediff/ | |
* | |
* @param numeric $from ID of the original article | |
* @param numeric $to ID of the modified article | |
* @return array | |
*/ | |
public function diff($from, $to) { | |
$result = ''; | |
App::uses('FineDiff', 'Articles.Lib'); | |
$src = $this->findById($from); | |
$dst = $this->findById($to); | |
$fields = array_keys($src['Article']); | |
$allowedFields = array('slug', 'title', 'content'); | |
foreach ($fields as $field) { | |
if (!in_array($field, $allowedFields)) { | |
continue; | |
} | |
$fineDiff = new FineDiff($src['Article'][$field], $dst['Article'][$field]); | |
$result[$field] = $fineDiff->renderDiffToHTML(); | |
} | |
return $result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment