bugfixes and date default format override by users
[ayans.git] / includes / news-node.php
blobfabf0df054fc5f59490ca176bea3bb6415b696a1
1 <?php
2 /**
3 * @category News
4 * @package News_Node
5 * @copyright Copyright (c) 2008, Bellière Ludovic
6 * @license http://opensource.org/licenses/mit-license.php MIT license
7 */
9 class News_Node_Exception extends Exception {}
11 /**
12 * @author Bellière Ludovic
13 * @category News
14 * @package News_Node
15 * @copyright Copyright (c) 2008, Bellière Ludovic
16 * @license http://opensource.org/licenses/mit-license.php MIT license
18 class news_node implements Countable {
20 public $_dateFormat = 'r';
21 public $_dateFormatMinimal = 'd.m.o';
22 protected $_content = array();
23 protected $_count = 0;
24 private $_filters = array();
25 private $_requiered_keynode;
26 private $_PDO;
27 private $_view;
28 private $_searchString;
30 const DEFAULT_VIEW = 0xEFFFF69C;
31 const SEARCH_VIEW = 0xE925030B;
32 const ARCHIVE_VIEW = 0x9A2B1B01;
34 const FORMAT_LIGHT = 'formatLight';
35 const FORMAT_FULL = 'formatFull';
37 public $_default_view_options = array(
38 'sql_limit' => '0, 10',
41 public function __construct() {
42 $this->_view = self::DEFAULT_VIEW;
45 public function setView($view) {
46 $this->_view = $view;
49 public function setPDO (PDO $pdo) {
50 $this->_PDO = $pdo;
53 /**
54 * Set the date format. If not used, default values will be used.
55 * @param string $formatFull Used for the full news view.
56 * @param string $formatLight Used for the light news view.
58 public function setDateFormat ($formatFull, $formatLight) {
59 $this->_dateFormat = $formatFull;
60 $this->_dateFormatMinimal = $formatLight;
63 /**
64 * Get a row by his id.
65 * If raw is true, get the row without escapement.
67 public function get ($key, $raw=false) {
68 if (is_array($key)) {
69 foreach ($key as $parent_key => $child_key) {
70 if (array_key_exists($child_key,$this->_content[$parent_key])) {
71 return (!is_array($this->_content[$parent_key]) && $raw == true) ? self::escape($this->_content[$parent_key]) : $this->_content[$parent_key];
76 if (array_key_exists($key,$this->_content)) {
77 return (!is_array($this->_content[$parent_key]) && $raw == true) ? self::escape($this->_content[$parent_key]) : $this->_content[$parent_key];
81 /**
82 * Add a filter function for the node $node
84 * @param string $function
85 * @param string $node
86 * @param integer $place
87 * @return void
88 * @throws News_Node_Exception for invalid type / not a function
90 public function add_filter($function,$node='all',$place=null) {
91 if (is_callable($function,true)) {
92 if (is_null($place)) {
93 $this->_filters[$node][] = $function;
94 } else {
95 if (!is_int($place)) {
96 throw new News_Node_Exception('The param `place\' is not an integer');
99 if (isset($this->_filters[$place])) {
100 $for = (is_array($function)) ? $function[0].'->'.$function[1] : $function ;
101 trigger_error('Replacement of filter number '.$place.' for content <em>'.$for.'</em>',E_USER_NOTICE);
104 $this->_filters[$node][$place] = $function;
106 } else {
107 throw new News_Node_Exception('The <em>function</em> parameter "'.$function.'" is not callable.');
111 public function render($reload=false, $paginate=false, $format='formatFull') {
112 try {
113 self::getNews($reload,$paginate);
114 } catch (News_Node_Exception $e) {
115 die ($e->getMessage());
117 $txt = '';
118 if ($reload) {
119 $txt = self::reloadCache($format);
120 } else {
121 foreach ($this->_content as $node) {
122 $txt.= $node['data'];
125 return $txt;
129 * Searches news for needle.
130 * @param string $needle The searched value.
132 public function search($needle) {
133 $this->_searchString = $needle;
134 self::setView(self::SEARCH_VIEW);
135 return true;
138 protected function getDate($timestamp,$context) {
139 switch ($context) {
140 case self::FORMAT_LIGHT:
141 $date = date($this->_dateFormatMinimal,$timestamp);
142 break;
143 case self::FORMAT_FULL:
144 $date = date($this->_dateFormat,$timestamp);
145 break;
147 return $date;
150 protected function add_nodes(array $content) {
151 foreach ($content as $node) {
152 if (!isset($this->_content['n-'.$node['id']])) {
153 $this->_content['n-'.$node['id']] = $node;
154 $this->_count++;
159 protected function escape ($content,$tag) {
160 foreach($this->_filters as $node => $filters) {
161 if ($node == 'all' || $tag == $node) {
162 foreach ($filters as $filter) {
163 $content = call_user_func_array($filter,array(&$content));
167 return $content;
171 * Fetch all data from cache or database.
173 private function getNews ($reload=false,$paginate=false) {
174 if (!$reload) {
175 $cacheData = scandir(CACHE_PATH);
176 // custom action for ARCHIVE_VIEW
177 if ($this->_view == self::ARCHIVE_VIEW) {
178 $elements = $paginate->elements;
179 $limit = explode(', ',str_replace('LIMIT ','',$paginate->get_sql_limit_statement()));
181 // ---
182 foreach ($cacheData as $file) {
183 if ($file[0] == '.') {
184 continue;
186 $id = substr($file,2);
187 // custom action for ARCHIVE_VIEW
188 if ($this->_view == self::ARCHIVE_VIEW) {
189 if ($id-1 < intval($limit[0])) {
190 continue;
192 if ($id-1 > intval($limit[1])) {
193 break;
196 // ---
197 if ($format == self::FORMAT_LIGHT) {
198 $file.= '.minimal';
200 $allnodes[] = array (
201 'id' => $id,
202 'type' => 'cache',
203 'data' => file_get_contents(CACHE_PATH.$file)
206 if (!isset($allnodes)) {
207 $this->_content[]['data'] = '<p>no news in database</p>';
208 } else {
209 $allnodes = array_reverse($allnodes);
210 self::add_nodes($allnodes);
212 } else {
213 switch ($this->_view) {
214 case self::DEFAULT_VIEW:
215 $PDOStatement = $this->_PDO->query('SELECT * FROM news ORDER BY id DESC LIMIT '.$this->_default_view_options['sql_limit']);
216 break;
217 case self::SEARCH_VIEW:
218 $PDOStatement = $this->_PDO->query('SELECT * FROM news WHERE text LIKE \'%'.addslashes($this->_searchString).'%\' ORDER BY id DESC');
219 break;
220 case self::ARCHIVE_VIEW:
221 if ($format == self::FORMAT_FULL) {
222 $PDOStatement = $this->_PDO->query('SELECT * FROM news ORDER BY id DESC LIMIT '.$this->_default_view_options['sql_limit']);
223 } else {
224 if ($paginate instanceof paginate) {
225 $PDOStatement = $this->_PDO->query('SELECT * FROM news ORDER BY id DESC '.$paginate->get_sql_limit_statement());
226 } else {
227 throw new News_Node_Exception('$paginate is not a instance of paginate object.');
230 break;
231 default:
232 throw new News_Node_Exception('View \''.$this->_view.'\' not registered.');
234 self::add_nodes($PDOStatement->fetchAll());
239 * Write all files in cache directory
241 private function reloadCache($format='full') {
242 $txt='';
243 $searchedTags = array('%key%', '%title%', '%text%', '%author%');
244 foreach($this->_content as $key => $data) {
245 $replaceString = array(
246 $key,
247 self::escape($data['title'],'title'),
248 self::escape($data['text'],'text'),
249 self::escape($data['author'],'author'),
251 $replaceDate = array(
252 self::getDate($data['postedon'],self::FORMAT_FULL),
253 (isset($data['editdon'])) ? self::getDate($data['editdon'],self::FORMAT_LIGHT) : 'Never'
255 $txt_tmp = file_get_contents('templates/_newsFull.tpl');
256 $txt_tmp = str_replace($searchedTags, $replaceString,$txt_tmp);
257 $txt_tmp = str_replace(array('%postdate%', '%editdate%'),$replaceDate,$txt_tmp);
259 $min_tmp = file_get_contents('templates/_newsMinimal.tpl');
260 $min_tmp = str_replace($searchedTags, $replaceString,$min_tmp);
261 $min_tmp = str_replace(array('%postdate%', '%editdate%'),$replaceDate,$min_tmp);
263 file_put_contents(CACHE_PATH.$key.'.minimal',$min_tmp);
264 file_put_contents(CACHE_PATH.$key,$txt_tmp);
266 if ($format == self::FORMAT_FULL) {
267 $txt.=$txt_tmp;
268 } else {
269 $txt.=$min_tmp;
272 unset($txt_tmp,$min_tmp);
274 return $txt;
277 ///////
278 // overload
279 ///////
281 public function __get($key) {
282 return $this->_content[$key];
285 protected function __isset($name) {
286 return isset($this->_content[$name]);
289 public function count() {
290 return $this->_count;