/library/News/Article.php
PHP | 441 lines | 264 code | 85 blank | 92 comment | 47 complexity | ca276c33caee98c671f6325d38ff30f2 MD5 | raw file
Possible License(s): LGPL-2.1
- <?php
- class News_Article extends Data_Store {
- // id: news/2008/01/01/my-news-article
- protected $_data = array(
- 'type' => 'News_Article',
- 'title' => '', // Max 100 chars
- 'name' => '', // Derived so max 100 chars
- 'date' => false, // DateTime object
- 'approved' => false,
- 'trash' => false,
- 'author_id' => '',
- 'author_name' => '',
- 'author_email' => '',
- 'author_ip' => '',
- 'author_host' => '',
- 'text_id' => '',
- 'has_more' => false
- );
- /**
- * (Unparsed) content of the article.
- *
- * @see {News_Article::setText()}
- * @see {News_Article::getText()}
- *
- * @var string
- */
- protected $_text = null;
- /**
- * Sets up this object with data from the specified article, or if the
- * argument is NULL, sets up a new News_Article object.
- *
- * @param string|NULL $id Article ID (format: news/2000/01/01/article-name)
- */
- public function __construct ($id = null) {
- $this->_indexes = array('News_Article_Index');
- parent::__construct($id);
- // Workaround until php 5.3, when you'll be able to serialize DateTime objects
- if (!($this->_data['date'] instanceof DateTime)) {
- $this->_data['date'] = date_create((string) $this->_data['date']);
- //$this->_data['date']->setTimezone(new DateTimeZone('UTC'));
- }
- }
- /**
- * Checks whether a particular article has existed previously,
- * but has been deleted. (Checks for a 'gone' flag);
- *
- * @param string $id Article id
- * @return boolean
- */
- public static function isGone ($id) {
- return self::hasShadow($id, 'gone');
- }
- /**
- * Checks whether a particular artricle has been moved.
- * If so, returns the new id
- *
- * @param string $id Article id
- * @return FALSE|string
- */
- public static function isRedirect ($id) {
- return self::getShadow($id, 'redirect');
- }
- /**
- * Return an article by ID
- *
- * @param string $id Article id
- * @return News_Article
- */
- public static function find ($id) {
- return new self($id);
- }
- /**
- * Returns an internal ID corresponding to the current data.
- *
- * @return string
- */
- protected function _makeId () {
- $date = clone $this->_data['date'];
- $date->setTimezone(new DateTimeZone('UTC'));
- return 'news/' . $date->format('Y/m/d/') . $this->_data['name'];
- }
- /**
- * Returns a unique name corresponding to the current data,
- * to create a unique ID.
- *
- * @return string
- */
- protected function _makeUniqueName () {
- $old_name = Inflector::urlize($this->_getOriginalData('title'));
- $new_name = Inflector::urlize($this->_data['title']);
- // Workaround until php 5.3 (change to clone)
- $old_date = date_create($this->_getOriginalData('date'));
- $old_date->setTimezone(new DateTimeZone('UTC'));
- $old_date = $old_date->format('Y/m/d/');
- $new_date = clone $this->_data['date'];
- $new_date->setTimezone(new DateTimeZone('UTC'));
- $new_date = $new_date->format('Y/m/d/');
- if ($this->_new || !($old_name == $new_name && $old_date == $new_date)) {
- $dir = self::$_dataDir . $this->_makeId();
- if ($this->_data['name'] != '') {
- $dir = dirname($dir) . '/';
- }
- $files = glob($dir . $new_name . '*');
- $count = 0;
- if (is_array($files)) {
- foreach ($files as $file) {
- if (preg_match('#^' . $new_name . '(?:-(\d+))?$#i', basename($file), $matches)) {
- if (count($matches) > 1) {
- list(,$number) = $matches;
- } else {
- $number = 1;
- }
- $count = max($count, max(1, (int) $number));
- }
- }
- }
-
- if ($count) {
- $new_name .= '-' . ($count + 1);
- }
- }
- return $new_name;
- }
- public function setApproved ($val) {
- $this->_data['approved'] = (bool) $val;
- return $this;
- }
- public function getText () {
- if ($this->_text === null) {
- $name = $this->_data['text_id'];
- if (!empty($name) && $this->hasAttachment($name)) {
- $this->_text = $this->getAttachment($name);
- } else {
- $this->_text = '';
- $this->_modified['text'] = true;
- }
- }
- return $this->_text;
- }
- public function setText ($value) {
- if ($this->getText() != $value) {
- $this->_text = $value;
- $this->set('has_more', (stripos($value, '<hr') !== false));
- $this->_modified['text'] = true;
- } else {
- unset($this->_modified['text']);
- }
- return $this;
- }
- public function getArticle ($email = false) {
- return $this->_getContent('article', $email);
- }
- public function getSummary ($email = false) {
- return $this->_getContent('summary', $email);
- }
-
- protected function _getContent ($method, $email) {
- $cache_id = $this->_id . '/' . $method . '-' . ($email ? 'email' : 'noemail');
- if (isset(self::$_cache[$cache_id])) {
- return self::$_cache[$cache_id];
- } else {
- $parsed = News_Parser::process($this->getText(), $method, $email);
- if (!$this->_new) {
- self::$_cache[$cache_id] = $parsed;
- }
- return $parsed;
- }
- }
- public function setTitle ($value) {
- $this->_data['title'] = substr($value, 0, 100);
- if (!$this->_new) {
- $this->_id = $this->_makeId();
- $this->_modified['id'] = true;
- }
- return $this;
- }
- public function setTrash ($val) {
- $this->_data['trash'] = (bool) $val;
- return $this;
- }
- public function setDate (DateTime $value) {
- $this->_data['date'] = $value;
- if (!$this->_new) {
- $this->_id = $this->_makeId();
- $this->_modified['id'] = true;
- }
- return $this;
- }
- public function save () {
- if ($this->_data['date'] == null) {
- $this->set('date', date_create());
- }
- if (trim($this->_data['title']) == '') {
- $this->set('title', 'Untitled Article');
- }
- if ($this->_new || isset($this->_modified['id'])) {
- $this->set('name', $this->_makeUniqueName());
- $this->_id = $this->_makeId();
- }
- if ($this->_new) {
- $this->_id = $this->_makeId();
- }
- if (isset($this->_modified['text'])) {
- $this->_data['text_id'] = 'text.' . date('YmdHis');
- $this->addAttachment($this->_data['text_id'], $this->_text); // TODO: gz
- self::$_cache->delete($this->_getOriginalData('id') . '/article-email');
- self::$_cache->delete($this->_getOriginalData('id') . '/article-noemail');
- self::$_cache->delete($this->_getOriginalData('id') . '/summary-email');
- self::$_cache->delete($this->_getOriginalData('id') . '/summary-noemail');
- }
- if (count($this->_modifiedAttachments) + count($this->_deletedAttachments) > 0) {
- self::$_cache->delete($this->_getOriginalData('id') . '/commentcount');
- }
- $original_id = (isset($this->_modified['id'])) ? $this->_getOriginalData('id') : false;
- // Workaround until php 5.3, when you'll be able to serialize DateTime objects
- //$this->_data['date']->setTimezone(new DateTimeZone('UTC'));
- $this->_data['date'] = $this->_data['date']->format(DateTime::ISO8601);
- parent::save();
- // Workaround until php 5.3, when you'll be able to serialize DateTime objects
- $this->_data['date'] = date_create((string) $this->_data['date']);
- // Create redirect if moved.
- if (false !== $original_id) {
- self::addShadow($original_id, 'redirect', $this->_id);
- }
- return $this;
- }
- /**
- * Deletes this article; sets 'gone' flag
- *
- * @return void
- */
- public function delete () {
- parent::delete();
- // Delete emails
- /* $filenames = glob(self::$_dataDir . $this->_getOriginalData('id') . '/resource-image.*');
- if ($filenames !== false) {
- foreach ($filenames as $filename) {
- try {
- $email = Resource_Email::find(file_get_contents($filename));
- $email->delete();
- } catch (Exception $e) {}
- }
- } */
- // Create deletion notice.
- self::addShadow($this->_getOriginalData('id'), 'gone');
- }
- public function addComment ($data) {
- $time = date_create();
- // Accept ids passed in to enable undo delete comment.
- if (!isset($data['id'])) {
- $time->setTimezone(new DateTimeZone('UTC'));
- $id = $time->format('YmdHis');
- } else {
- $id = $data['id'];
- }
- $text = isset($data['text']) ? $data['text'] : '';
- $comment_data = array(
- 'id' => $id,
- 'author_id' => isset($data['author_id']) ? $data['author_id'] : '',
- 'author_name' => isset($data['author_name']) ? $data['author_name'] : '',
- 'author_email' => isset($data['author_email']) ? $data['author_email'] : '',
- 'author_ip' => isset($data['author_ip']) ? $data['author_ip'] : '',
- 'author_host' => isset($data['author_host']) ? $data['author_host'] : '',
- 'date' => isset($data['date']) ? $data['date'] : $time->format(DateTime::ISO8601),
- 'text' => $text,
- 'text_email' => News_Parser::processComment($text, true),
- 'text_noemail' => News_Parser::processComment($text, false)
- );
- // This assumes that the comment ids are integers.
- // (Which they should be!)
- while (true) {
- try {
- $this->addAttachment('comment.' . $id, serialize($comment_data));
- break;
- } catch (Data_Store_AttachmentExistsException $e) {
- $comment_data['id'] = ++$id;
- }
- }
- return $comment_data;
- }
- /**
- * Deletes a particular comment. The comment id is the time it was posted,
- * in "YmdHis" format.
- *
- * @param string $comment_id
- * @return News_Article Fluent Interface
- */
- public function deleteComment ($comment_id) {
- $name = 'comment.' . $comment_id;
-
- if ($this->hasAttachment($name)) {
- $this->deleteAttachment($name);
- } else {
- throw new Exception ('Comment ' . $this->_id . '/' . $comment_id . ' does not exist');
- }
- return $this;
- }
- /**
- * Gets the data for a particular comment.
- * The comment id is the time it was posted, in "YmdHis" format.
- *
- * @param string $comment_id
- * @return array
- */
- public function getComment ($comment_id) {
- $name = 'comment.' . $comment_id;
- if ($this->hasAttachment($name)) {
- $comment = unserialize($this->getAttachment($name));
- $comment['date'] = date_create($comment['date']);
- } else {
- throw new Exception ('Comment ' . $this->_id . '/' . $comment_id . ' does not exist');
- }
- return $comment;
- }
- /**
- * Returns all of the comments for this article
- *
- * @return Array
- */
- public function getComments () {
- $comments = array();
- $filenames = glob(self::$_dataDir . $this->_getOriginalData('id') . '/comment.*');
-
- if ($filenames !== false) {
- foreach ($filenames as $filename) {
- $comment = unserialize(file_get_contents($filename));
- $comment['date'] = date_create($comment['date']);
- $comments[] = $comment;
- }
- }
- return $comments;
- }
- public function getCommentCount () {
- if ($this->_new) {
- return 0;
- }
- $cache_id = $this->_getOriginalData('id') . '/commentcount';
- if (isset(self::$_cache[$cache_id])) {
- return self::$_cache[$cache_id];
- } else {
- $comments = glob(self::$_dataDir . $this->_getOriginalData('id') . '/comment.*');
- $count = (int) ($comments === false ? 0 : count($comments));
- self::$_cache[$cache_id] = $count;
- }
- return $count;
- }
- public static function getAll () {
- $len = strlen(self::$_dataDir);
- $files = glob(self::$_dataDir . 'news/*/*/*/*/data');
- $return = array();
- if ($files !== false) {
- foreach ((array) $files as $file) {
- $id = substr(substr($file, $len), 0, -5);
- $return[$id] = new self($id);
- }
- }
- return $return;
- }
- }