Completed
Push — 2.0 ( 36a704...82895b )
by Christopher
02:22
created

SelectScope::getVirtualColumns()   C

Complexity

Conditions 8
Paths 7

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
cc 8
eloc 16
c 3
b 2
f 0
nc 7
nop 2
dl 0
loc 28
rs 5.3846
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
71
        return $query;
72
    }
73
74
    /**
75
     * Gets a list of all virtual columns present in given $query's SELECT clause.
76
     *
77
     * This method will alter the given Query object removing any virtual column
78
     * present in its SELECT clause in order to avoid incorrect SQL statements.
79
     * Selected virtual columns should be fetched after query is executed using
80
     * mapReduce or similar.
81
     *
82
     * @param \Cake\ORM\Query $query The query object to be scoped
83
     * @param string|null $bundle Consider attributes only for a specific bundle
84
     * @return array List of virtual columns names
85
     */
86
    public function getVirtualColumns(Query $query, $bundle = null)
87
    {
88
        $selectClause = (array)$query->clause('select');
89
        if (empty($selectClause)) {
90
            return array_keys($this->_toolbox->attributes($bundle));
91
        }
92
93
        $selectedVirtual = [];
94
        $virtualColumns = array_keys($this->_toolbox->attributes($bundle));
95
96
        foreach ($selectClause as $index => $column) {
97
            list($table, $column) = pluginSplit($column);
98
            if ((empty($table) || $table == $this->_table->alias()) &&
99
                in_array($column, $virtualColumns)
100
            ) {
101
                $selectedVirtual[$index] = $column;
102
                unset($selectClause[$index]);
103
            }
104
        }
105
106
        if (empty($selectClause) && !empty($selectedVirtual)) {
107
            $selectClause[] = $this->_table->primaryKey();
108
        }
109
110
        $query->select($selectClause, true);
111
112
        return $selectedVirtual;
113
    }
114
}
115