Completed
Push — 2.0 ( 37e932...3a3557 )
by Christopher
04:07
created

SelectScope   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 11
c 2
b 1
f 0
lcom 1
cbo 3
dl 0
loc 97
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A scope() 0 5 1
D getVirtualColumns() 0 33 9
1
<?php
2
/**
3
 * Licensed under The GPL-3.0 License
4
 * For full copyright and license information, please see the LICENSE.txt
5
 * Redistributions of files must retain the above copyright notice.
6
 *
7
 * @since    2.0.0
8
 * @author   Christopher Castro <[email protected]>
9
 * @link     http://www.quickappscms.org
10
 * @license  http://opensource.org/licenses/gpl-3.0.html GPL-3.0 License
11
 */
12
namespace Eav\Model\Behavior\QueryScope;
13
14
use Cake\ORM\Query;
15
use Cake\ORM\Table;
16
use Eav\Model\Behavior\EavToolbox;
17
use Eav\Model\Behavior\QueryScope\QueryScopeInterface;
18
19
/**
20
 * Used by EAV Behavior to scope SELECT statements.
21
 */
22
class SelectScope implements QueryScopeInterface
23
{
24
25
    /**
26
     * The table being managed.
27
     *
28
     * @var \Cake\ORM\Table
29
     */
30
    protected $_table = null;
31
32
    /**
33
     * Instance of toolbox.
34
     *
35
     * @var \Eav\Model\Behavior\EavToolbox
36
     */
37
    protected $_toolbox = null;
38
39
    /**
40
     * {@inheritDoc}
41
     */
42
    public function __construct(Table $table)
43
    {
44
        $this->_table = $table;
45
        $this->_toolbox = new EavToolbox($table);
46
    }
47
48
    /**
49
     * {@inheritDoc}
50
     *
51
     * If "SELECT *" is performed
52
     * this behavior will fetch all virtual columns its values.
53
     *
54
     * Column aliasing are fully supported, allowing to create alias for virtual
55
     * columns. For instance:
56
     *
57
     * ```php
58
     * $article = $this->Articles->find()
59
     *     ->select(['aliased_virtual' => 'some_eav_column', 'body'])
60
     *     ->where(['Articles.id' => $id])
61
     *     ->limit(1)
62
     *     ->first();
63
     *
64
     * echo $article->get('aliased_virtual');
65
     * ```
66
     */
67
    public function scope(Query $query, $bundle = null)
68
    {
69
        $this->getVirtualColumns($query, $bundle);
70
        return $query;
71
    }
72
73
    /**
74
     * Gets a list of all virtual columns present in given $query's SELECT clause.
75
     *
76
     * This method will alter the given Query object removing any virtual column
77
     * present in its SELECT clause in order to avoid incorrect SQL statements.
78
     * Selected virtual columns should be fetched after query is executed using
79
     * mapReduce or similar.
80
     *
81
     * @param \Cake\ORM\Query $query The query object to be scoped
82
     * @param string|null $bundle Consider attributes only for a specific bundle
83
     * @return array List of virtual columns names
84
     */
85
    public function getVirtualColumns(Query $query, $bundle = null)
86
    {
87
        static $selectedVirtual = [];
88
        $cacheKey = spl_object_hash($query) . $bundle;
89
        if (isset($selectedVirtual[$cacheKey])) {
90
            return $selectedVirtual[$cacheKey];
91
        }
92
93
        $selectClause = (array)$query->clause('select');
94
        if (empty($selectClause)) {
95
            $selectedVirtual[$cacheKey] = array_keys($this->_toolbox->attributes($bundle));
96
            return $selectedVirtual[$cacheKey];
97
        }
98
99
        $selectedVirtual[$cacheKey] = [];
100
        $virtualColumns = array_keys($this->_toolbox->attributes($bundle));
101
        foreach ($selectClause as $index => $column) {
102
            list($table, $column) = pluginSplit($column);
103
            if ((empty($table) || $table == $this->_table->alias()) &&
104
                in_array($column, $virtualColumns)
105
            ) {
106
                $selectedVirtual[$cacheKey][$index] = $column;
107
                unset($selectClause[$index]);
108
            }
109
        }
110
111
        if (empty($selectClause) && !empty($selectedVirtual[$cacheKey])) {
112
            $selectClause[] = $this->_table->primaryKey();
113
        }
114
115
        $query->select($selectClause, true);
116
        return $selectedVirtual[$cacheKey];
117
    }
118
}
119