Dotclear

source: inc/core/class.dc.meta.php @ 877:e012da998f83

Revision 877:e012da998f83, 14.8 KB checked in by Dsls <dsls@…>, 13 years ago (diff)

Entries passwords will be a dedicated plugin.

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14/**
15@ingroup DC_CORE
16@nosubgrouping
17@brief Dotclear metadata class.
18
19Dotclear metadata class instance is provided by dcCore $meta property.
20*/
21class dcMeta
22{
23     private $core; ///< <b>dcCore</b> dcCore instance
24     private $con;  ///< <b>connection</b>   Database connection object
25     private $table;     ///< <b>string</b> Media table name
26     
27     /**
28     Object constructor.
29     
30     @param    core      <b>dcCore</b>       dcCore instance
31     */
32     public function __construct($core)
33     {
34          $this->core =& $core;
35          $this->con =& $this->core->con;
36          $this->table = $this->core->prefix.'meta';
37     }
38     
39     /**
40     Splits up comma-separated values into an array of
41     unique, URL-proof metadata values.
42     
43     @param    str       <b>string</b>       Comma-separated metadata.
44     
45     @return   <b>Array</b>   The array of sanitized metadata
46     */
47     public function splitMetaValues($str)
48     {
49          $res = array();
50          foreach (explode(',',$str) as $i => $tag)
51          {
52               $tag = trim($tag);
53               $tag = self::sanitizeMetaID($tag);
54               
55               if ($tag != false) {
56                    $res[$i] = $tag;
57               }
58          }
59         
60          return array_unique($res);
61     }
62     
63     /**
64     Make a metadata ID URL-proof.
65     
66     @param    str       <b>string</b>  the metadata ID.
67     
68     @return   <b>string</b>  The sanitized metadata
69     */
70     public static function sanitizeMetaID($str)
71     {
72          return text::tidyURL($str,false,true);
73     }
74     
75     /**
76     Converts serialized metadata (for instance in dc_post post_meta)
77     into a meta array.
78     
79     @param    str       <b>string</b>  the serialized metadata.
80     
81     @return   <b>Array</b>   the resulting array of post meta
82     */
83     public function getMetaArray($str)
84     {
85          $meta = @unserialize($str);
86         
87          if (!is_array($meta)) {
88               return array();
89          }
90         
91          return $meta;
92     }
93     
94     /**
95     Converts serialized metadata (for instance in dc_post post_meta)
96     into a comma-separated meta list for a given type.
97     
98     @param    str       <b>string</b>  the serialized metadata.
99     @param    type <b>string</b>  meta type to retrieve metaIDs from.
100     
101     @return   <b>string</b>  the comma-separated list of meta
102     */
103     public function getMetaStr($str,$type)
104     {
105          $meta = $this->getMetaArray($str);
106         
107          if (!isset($meta[$type])) {
108               return '';
109          }
110         
111          return implode(', ',$meta[$type]);
112     }
113     
114     /**
115     Converts serialized metadata (for instance in dc_post post_meta)
116     into a "fetchable" metadata record.
117     
118     @param    str       <b>string</b>  the serialized metadata.
119     @param    type <b>string</b>  meta type to retrieve metaIDs from.
120     
121     @return   <b>record</b>  the meta recordset
122     */
123     public function getMetaRecordset($str,$type)
124     {
125          $meta = $this->getMetaArray($str);
126          $data = array();
127         
128          if (isset($meta[$type]))
129          {
130               foreach ($meta[$type] as $v)
131               {
132                    $data[] = array(
133                         'meta_id' => $v,
134                         'meta_type' => $type,
135                         'meta_id_lower' => mb_strtolower($v),
136                         'count' => 0,
137                         'percent' => 0,
138                         'roundpercent' => 0
139                    );
140               }
141          }
142         
143          return staticRecord::newFromArray($data);
144     }
145     
146     /**
147     @deprecated since version 2.2 : $core->meta is always defined
148     @see getMetaRecordset
149     static version of getMetaRecordset
150     */
151     public static function getMetaRecord($core,$str,$type)
152     {
153          $meta = new self($core);
154          return $meta->getMetaRecordset($str,$type);
155     }
156     
157     /**
158     Checks whether the current user is allowed to change post meta
159     An exception is thrown if user is not allowed.
160     
161     @param    post_id   <b>string</b>  the post_id to check.
162     */
163     private function checkPermissionsOnPost($post_id)
164     {
165          $post_id = (integer) $post_id;
166         
167          if (!$this->core->auth->check('usage,contentadmin',$this->core->blog->id)) {
168               throw new Exception(__('You are not allowed to change this entry status'));
169          }
170         
171          #�If user can only publish, we need to check the post's owner
172          if (!$this->core->auth->check('contentadmin',$this->core->blog->id))
173          {
174               $strReq = 'SELECT post_id '.
175                         'FROM '.$this->core->prefix.'post '.
176                         'WHERE post_id = '.$post_id.' '.
177                         "AND user_id = '".$this->con->escape($this->core->auth->userID())."' ";
178               
179               $rs = $this->con->select($strReq);
180               
181               if ($rs->isEmpty()) {
182                    throw new Exception(__('You are not allowed to change this entry status'));
183               }
184          }
185     }
186     
187     /**
188     Updates serialized post_meta information with dc_meta table information.
189     
190     @param    post_id   <b>string</b>  the post_id to update.
191     */
192     private function updatePostMeta($post_id)
193     {
194          $post_id = (integer) $post_id;
195         
196          $strReq = 'SELECT meta_id, meta_type '.
197                    'FROM '.$this->table.' '.
198                    'WHERE post_id = '.$post_id.' ';
199         
200          $rsmeta = $this->con->select($strReq);
201         
202          $meta = array();
203          foreach ($rsmeta as $r) {
204               $meta[$r->meta_type][] = $r->meta_id;
205          }
206         
207          $post_meta = serialize($meta);
208         
209          $cur = $this->con->openCursor($this->core->prefix.'post');
210          $cur->post_meta = $post_meta;
211         
212          $cur->update('WHERE post_id = '.$post_id);
213          $this->core->blog->triggerBlog();
214     }
215     
216     /**
217     Retrieves posts corresponding to given meta criteria.
218     <b>$params</b> is an array taking the following optional parameters:
219     - meta_id : get posts having meta id
220     - meta_type : get posts having meta type
221     
222     @param    params    <b>array</b>   Parameters
223     @param    count_only     <b>boolean</b>      Only counts results
224     
225     @return   <b>record</b>  the resulting posts record
226     */
227     public function getPostsByMeta($params=array(),$count_only=false)
228     {
229          if (!isset($params['meta_id'])) {
230               return null;
231          }
232         
233          $params['from'] = ', '.$this->table.' META ';
234          $params['sql'] = 'AND META.post_id = P.post_id ';
235         
236          $params['sql'] .= "AND META.meta_id = '".$this->con->escape($params['meta_id'])."' ";
237         
238          if (!empty($params['meta_type'])) {
239               $params['sql'] .= "AND META.meta_type = '".$this->con->escape($params['meta_type'])."' ";
240               unset($params['meta_type']);
241          }
242         
243          unset($params['meta_id']);
244         
245          return $this->core->blog->getPosts($params,$count_only);
246     }
247     
248     /**
249     @deprecated since 2.2. Use getMetadata and computeMetaStats instead.
250     Generic-purpose metadata retrieval : gets metadatas according to given
251     criteria. Metadata get enriched with stastistics columns (only relevant
252     if limit parameter is not set). Metadata are sorted by post count
253     descending
254     
255     @param    type <b>string</b>  if not null, get metas having the given type
256     @param    limit     <b>string</b>  if not null, number of max fetched metas
257     @param    meta_id   <b>string</b>  if not null, get metas having the given id
258     @param    post_id   <b>string</b>  if not null, get metas for the given post id
259     
260     @return   <b>record</b>  the meta recordset
261     */
262     public function getMeta($type=null,$limit=null,$meta_id=null,$post_id=null) {
263          $params = array();
264         
265          if ($type != null)
266               $params['meta_type'] = $type;
267          if ($limit != null)
268               $params['limit'] = $limit;
269          if ($meta_id != null)
270               $params['meta_id'] = $meta_id;
271          if ($meta_id != null)
272               $params['post_id'] = $post_id;
273          $meta = $this->getMetadata($params, false);
274          return $this->computeMetaStats($meta);
275     }
276     
277     /**
278     Generic-purpose metadata retrieval : gets metadatas according to given
279     criteria. <b>$params</b> is an array taking the following
280     optionnal parameters:
281     
282     - type: get metas having the given type
283     - meta_id: if not null, get metas having the given id
284     - post_id: get metas for the given post id
285     - limit: number of max fetched metas
286     - order: results order (default : posts count DESC)
287     
288     @param    params         <b>array</b>        Parameters
289     @param    count_only     <b>boolean</b>      Only counts results
290     
291     @return   <b>record</b>  the resulting comments record
292     */
293     public function getMetadata($params=array(), $count_only=false)
294     {
295          if ($count_only) {
296               $strReq = 'SELECT count(distinct M.meta_id) ';
297          } else {
298               $strReq = 'SELECT M.meta_id, M.meta_type, COUNT(M.post_id) as count ';
299          }
300         
301          $strReq .=
302          'FROM '.$this->table.' M LEFT JOIN '.$this->core->prefix.'post P '.
303          'ON M.post_id = P.post_id '.
304          "WHERE P.blog_id = '".$this->con->escape($this->core->blog->id)."' ";
305         
306          if (isset($params['meta_type'])) {
307               $strReq .= " AND meta_type = '".$this->con->escape($params['meta_type'])."' ";
308          }
309         
310          if (isset($params['meta_id'])) {
311               $strReq .= " AND meta_id = '".$this->con->escape($params['meta_id'])."' ";
312          }
313         
314          if (isset($params['post_id'])) {
315               $strReq .= ' AND P.post_id '.$this->con->in($params['post_id']).' ';
316          }
317         
318          if (!$this->core->auth->check('contentadmin',$this->core->blog->id)) {
319               $strReq .= 'AND ((post_status = 1) ';
320               
321               if ($this->core->auth->userID()) {
322                    $strReq .= "OR P.user_id = '".$this->con->escape($this->core->auth->userID())."')";
323               } else {
324                    $strReq .= ') ';
325               }
326          }
327         
328          if (!$count_only) {
329               if (!isset($params['order'])) {
330                    $params['order'] = 'count DESC';
331               }
332               
333               $strReq .=
334               'GROUP BY meta_id,meta_type,P.blog_id '.
335               'ORDER BY '.$params['order'];
336               
337               if (isset($params['limit'])) {
338                    $strReq .= $this->con->limit($params['limit']);
339               }
340          }
341         
342          $meta = $this->con->select($strReq);
343          return $meta;
344     }
345     
346     /**
347     Computes statistics from a metadata recordset.
348     Each record gets enriched with lowercase name, percent and roundpercent columns
349     
350     @param    rs   <b>record</b>  recordset to enrich
351     
352     @return   <b>record</b>  the enriched recordset
353     */
354     public function computeMetaStats($meta) {
355          $meta_static = $meta->toStatic();
356         
357          $max = array();
358          foreach ($meta_static as $m)
359          {
360               $type = $m->meta_type;
361               if (!isset($max[$type])) {
362                    $max[$type] = $m->count;
363               } else {
364                    if ($m->count > $max[$type]) {
365                         $max[$type] = $m->count;
366                    }
367               }
368          }
369         
370          foreach ($meta_static as $m)
371          {
372               $m->set('meta_id_lower',mb_strtolower($m->meta_id));
373               
374               $count = $m->count;
375               $percent = ((integer) $m->count) * 100 / $max[$m->meta_type];
376               
377               $m->set('percent',(integer) round($percent));
378               $m->set('roundpercent',round($percent/10)*10);
379          }
380         
381          return $meta_static;
382     }
383     
384     /**
385     Adds a metadata to a post.
386     
387     @param    post_id   <b>integer</b> the post id
388     @param    type <b>string</b>  meta type
389     @param    value     <b>integer</b> meta value
390     */
391     public function setPostMeta($post_id,$type,$value)
392     {
393          $this->checkPermissionsOnPost($post_id);
394         
395          $value = trim($value);
396          if ($value === false) { return; }
397         
398          $cur = $this->con->openCursor($this->table);
399         
400          $cur->post_id = (integer) $post_id;
401          $cur->meta_id = (string) $value;
402          $cur->meta_type = (string) $type;
403         
404          $cur->insert();
405          $this->updatePostMeta((integer) $post_id);
406     }
407     
408     /**
409     Removes metadata from a post.
410     
411     @param    post_id   <b>integer</b> the post id
412     @param    type <b>string</b>  meta type (if null, delete all types)
413     @param    value     <b>integer</b> meta value (if null, delete all values)
414     */
415     public function delPostMeta($post_id,$type=null,$meta_id=null)
416     {
417          $post_id = (integer) $post_id;
418         
419          $this->checkPermissionsOnPost($post_id);
420         
421          $strReq = 'DELETE FROM '.$this->table.' '.
422                    'WHERE post_id = '.$post_id;
423         
424          if ($type !== null) {
425               $strReq .= " AND meta_type = '".$this->con->escape($type)."' ";
426          }
427         
428          if ($meta_id !== null) {
429               $strReq .= " AND meta_id = '".$this->con->escape($meta_id)."' ";
430          }
431         
432          $this->con->execute($strReq);
433          $this->updatePostMeta((integer) $post_id);
434     }
435     
436     /**
437     Mass updates metadata for a given post_type.
438     
439     @param    meta_id        <b>integer</b> old value
440     @param    new_meta  <b>integer</b> new value
441     @param    type <b>string</b>  meta type (if null, select all types)
442     @param    post_type <b>integer</b> impacted post_type (if null, select all types)
443     @return   <b>boolean</b> true if at least 1 post has been impacted
444     */
445     public function updateMeta($meta_id,$new_meta_id,$type=null,$post_type=null)
446     {
447          $new_meta_id = self::sanitizeMetaID($new_meta_id);
448         
449          if ($new_meta_id == $meta_id) {
450               return true;
451          }
452         
453          $getReq = 'SELECT M.post_id '.
454                    'FROM '.$this->table.' M, '.$this->core->prefix.'post P '.
455                    'WHERE P.post_id = M.post_id '.
456                    "AND P.blog_id = '".$this->con->escape($this->core->blog->id)."' ".
457                    "AND meta_id = '%s' ";
458         
459          if (!$this->core->auth->check('contentadmin',$this->core->blog->id)) {
460               $getReq .= "AND P.user_id = '".$this->con->escape($this->core->auth->userID())."' ";
461          }
462          if ($post_type !== null) {
463               $getReq .= "AND P.post_type = '".$this->con->escape($post_type)."' ";
464          }
465         
466          $delReq = 'DELETE FROM '.$this->table.' '.
467                    'WHERE post_id IN (%s) '.
468                    "AND meta_id = '%s' ";
469         
470          $updReq = 'UPDATE '.$this->table.' '.
471                    "SET meta_id = '%s' ".
472                    'WHERE post_id IN (%s) '.
473                    "AND meta_id = '%s' ";
474         
475          if ($type !== null) {
476               $plus = " AND meta_type = '%s' ";
477               $getReq .= $plus;
478               $delReq .= $plus;
479               $updReq .= $plus;
480          }
481         
482          $to_update = $to_remove = array();
483         
484          $meta = $this->con->select(sprintf($getReq,$this->con->escape($meta_id),
485                                   $this->con->escape($type)));
486         
487          foreach ($meta as $m) {
488               $to_update[] = $m->post_id;
489          }
490         
491          if (empty($to_update)) {
492               return false;
493          }
494         
495          $meta = $this->con->select(sprintf($getReq,$new_meta_id,$type));
496          foreach ($meta as $m) {
497               if (in_array($m->post_id,$to_update)) {
498                    $to_remove[] = $m->post_id;
499                    unset($to_update[array_search($m->post_id,$to_update)]);
500               }
501          }
502         
503          # Delete duplicate meta
504          if (!empty($to_remove))
505          {
506               $this->con->execute(sprintf($delReq,implode(',',$to_remove),
507                                   $this->con->escape($meta_id),
508                                   $this->con->escape($type)));
509               
510               foreach ($to_remove as $post_id) {
511                    $this->updatePostMeta($post_id);
512               }
513          }
514         
515          # Update meta
516          if (!empty($to_update))
517          {
518               $this->con->execute(sprintf($updReq,$this->con->escape($new_meta_id),
519                                   implode(',',$to_update),
520                                   $this->con->escape($meta_id),
521                                   $this->con->escape($type)));
522               
523               foreach ($to_update as $post_id) {
524                    $this->updatePostMeta($post_id);
525               }
526          }
527         
528          return true;
529     }
530     
531     /**
532     Mass delete metadata for a given post_type.
533     
534     @param    meta_id        <b>integer</b> meta value
535     @param    type <b>string</b>  meta type (if null, select all types)
536     @param    post_type <b>integer</b> impacted post_type (if null, select all types)
537     @return   <b>Array</b>   the list of impacted post_ids
538     */
539     public function delMeta($meta_id,$type=null,$post_type=null)
540     {
541          $strReq = 'SELECT M.post_id '.
542                    'FROM '.$this->table.' M, '.$this->core->prefix.'post P '.
543                    'WHERE P.post_id = M.post_id '.
544                    "AND P.blog_id = '".$this->con->escape($this->core->blog->id)."' ".
545                    "AND meta_id = '".$this->con->escape($meta_id)."' ";
546         
547          if ($type !== null) {
548               $strReq .= " AND meta_type = '".$this->con->escape($type)."' ";
549          }
550         
551          if ($post_type !== null) {
552               $strReq .= " AND P.post_type = '".$this->con->escape($post_type)."' ";
553          }
554         
555          $posts = $this->con->select($strReq);
556         
557          if (count($posts) == 0) return array();
558         
559          $ids = array();
560          foreach ($posts as $p) {
561               $ids[] = $p->post_id;
562          }
563         
564          $strReq = 'DELETE FROM '.$this->table.' '.
565                    'WHERE post_id IN ('.implode(',',$ids).') '.
566                    "AND meta_id = '".$this->con->escape($meta_id)."' ";
567         
568          if ($type !== null) {
569               $strReq .= " AND meta_type = '".$this->con->escape($type)."' ";
570          }
571         
572          $rs = $this->con->execute($strReq);
573         
574          foreach ($ids as $post_id) {
575               $this->updatePostMeta($post_id);
576          }
577         
578          return $ids;
579     }
580}
581?>
Note: See TracBrowser for help on using the repository browser.

Sites map