Dotclear

source: inc/core/class.dc.meta.php @ 3874:ab8368569446

Revision 3874:ab8368569446, 18.8 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

short notation for array (array() → [])

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

Sites map