Skip to content

Instantly share code, notes, and snippets.

@mamchenkov
Created August 26, 2014 06:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mamchenkov/4ffd280451f47db01f6d to your computer and use it in GitHub Desktop.
Save mamchenkov/4ffd280451f47db01f6d to your computer and use it in GitHub Desktop.
Saving Article's draft in CakePHP 2
<?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