Completed
Push — 2.0 ( 184f2d...b904ee )
by Christopher
04:56
created

EavToolbox::isSearchable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 4
rs 10
c 1
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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;
13
14
use Cake\Database\Type;
15
use Cake\Datasource\EntityInterface;
16
use Cake\ORM\Entity;
17
use Cake\ORM\Table;
18
use Cake\ORM\TableRegistry;
19
use Cake\Utility\Inflector;
20
21
/**
22
 * Support class for EAV behavior.
23
 */
24
class EavToolbox
25
{
26
27
    /**
28
     * List of accepted value types.
29
     *
30
     * @var array
31
     */
32
    public static $types = [
33
        'biginteger',
34
        'binary',
35
        'date',
36
        'float',
37
        'decimal',
38
        'integer',
39
        'time',
40
        'datetime',
41
        'timestamp',
42
        'uuid',
43
        'string',
44
        'text',
45
        'boolean',
46
    ];
47
48
    /**
49
     * The table being managed.
50
     *
51
     * @var \Cake\ORM\Table
52
     */
53
    protected $_table = null;
54
55
    /**
56
     * Attributes index by bundle, and by name within each bundle.
57
     *
58
     * ```php
59
     * [
60
     *     'administrator' => [
61
     *         'admin-address' => [
62
     *             'type' => 'varchar',
63
     *             'searchable' => false
64
     *         ],
65
     *         'admin-phone' => [
66
     *             'type' => 'varchar',
67
     *             'searchable' => true
68
     *         ]
69
     *     ],
70
     *     'editor' => [
71
     *         'editor-last-login' => [
72
     *             'type' => 'datetime',
73
     *             'searchable' => false,
74
     *         ]
75
     *     ]
76
     * ]
77
     * ```
78
     *
79
     * @var array
80
     */
81
    protected $_attributes = [];
82
83
    /**
84
     * Constructor.
85
     *
86
     * @param \Cake\ORM\Table $table The table being handled
87
     */
88
    public function __construct(Table $table)
89
    {
90
        $this->_table = $table;
91
    }
92
93
    /**
94
     * Gets a clean column name from query expression.
95
     *
96
     * ### Example:
97
     *
98
     * ```php
99
     * EavToolbox::columnName('Tablename.some_column');
100
     * // returns "some_column"
101
     *
102
     * EavToolbox::columnName('my_column');
103
     * // returns "my_column"
104
     * ```
105
     *
106
     * @param string $column Column name from query
107
     * @return string
108
     */
109
    public static function columnName($column)
110
    {
111
        list($tableName, $fieldName) = pluginSplit((string)$column);
112
        if (!$fieldName) {
113
            $fieldName = $tableName;
114
        }
115
        $fieldName = preg_replace('/\s{2,}/', ' ', $fieldName);
116
        list($fieldName, ) = explode(' ', trim($fieldName));
117
        return $fieldName;
118
    }
119
120
    /**
121
     * Checks if the provided entity has defined certain $property, regardless of
122
     * its value.
123
     *
124
     * @param \Cake\ORM\Entity $entity The entity to check
125
     * @param string $property The property name
126
     * @return bool True if exists
127
     */
128
    public function propertyExists(Entity $entity, $property)
129
    {
130
        $entityArray = $entity->toArray();
131
        return array_key_exists($property, $entityArray);
132
    }
133
134
    /**
135
     * Marshalls flat data into PHP objects.
136
     *
137
     * @param mixed $value The value to convert
138
     * @param string $type Type identifier, `integer`, `float`, etc
139
     * @return mixed Converted value
140
     */
141
    public function marshal($value, $type)
142
    {
143
        return Type::build($type)->marshal($value);
144
    }
145
146
    /**
147
     * Gets all attributes added to this table.
148
     *
149
     * @param string|null $bundle Get attributes within given bundle, or all of them
150
     *  regardless of the bundle if not provided
151
     * @return array List of attributes indexed by name (virtual column name)
152
     */
153
    public function attributes($bundle = null)
154
    {
155
        $key = empty($bundle) ? '@all' : $bundle;
156
        if (isset($this->_attributes[$key])) {
157
            return $this->_attributes[$key];
158
        }
159
160
        $this->_attributes[$key] = [];
161
        $conditions = ['EavAttributes.table_alias' => $this->_table->table()];
162
        if (!empty($bundle)) {
163
            $conditions['EavAttributes.bundle'] = $bundle;
164
        }
165
166
        $cacheKey = $this->_table->table() . '_' . $key;
167
        $attrs = TableRegistry::get('Eav.EavAttributes')
168
            ->find()
169
            ->cache($cacheKey, 'eav_table_attrs')
170
            ->where($conditions)
171
            ->all()
172
            ->toArray();
173
        foreach ($attrs as $attr) {
174
            $this->_attributes[$key][$attr->get('name')] = $attr;
175
        }
176
177
        return $this->attributes($bundle);
178
    }
179
180
    /**
181
     * Gets a list of attribute names.
182
     *
183
     * @param string $bundle Filter by bundle name
184
     * @return array
185
     */
186
    public function getAttributeNames($bundle = null)
187
    {
188
        $attributes = $this->attributes($bundle);
189
        return array_keys($attributes);
190
    }
191
192
    /**
193
     * Calculates entity's primary key.
194
     *
195
     * If PK is composed of multiple columns they will be merged with `:` symbol.
196
     * For example, consider `Users` table with composed PK <nick, email>, then for
197
     * certain User entity this method could return:
198
     *
199
     *     john-locke:[email protected]
200
     *
201
     * @param \Cake\Datasource\EntityInterface $entity The entity
202
     * @return string
203
     */
204 View Code Duplication
    public function getEntityId(EntityInterface $entity)
205
    {
206
        $pk = [];
207
        $keys = $this->_table->primaryKey();
208
        $keys = !is_array($keys) ? [$keys] : $keys;
209
        foreach ($keys as $key) {
210
            $pk[] = $entity->get($key);
211
        }
212
        return implode(':', $pk);
213
    }
214
215
    /**
216
     * Gets attribute's EAV type.
217
     *
218
     * @param string $attrName Attribute name
219
     * @return string Attribute's EAV type
220
     * @see \Eav\Model\Behavior\EavBehavior::_mapType()
221
     */
222
    public function getType($attrName)
223
    {
224
        return $this->mapType($this->attributes()[$attrName]->get('type'));
225
    }
226
227
    /**
228
     * Gets attribute's bundle.
229
     *
230
     * @param string $attrName Attribute name
231
     * @return string|null
232
     */
233
    public function getBundle($attrName)
234
    {
235
        return $this->attributes()[$attrName]->get('bundle');
236
    }
237
238
    /**
239
     * Whether the given attribute can be used in WHERE clauses.
240
     *
241
     * @param string $attrName Attribute name
242
     * @return bool
243
     */
244
    public function isSearchable($attrName)
245
    {
246
        return (bool)$this->attributes()[$attrName]->get('searchable');
247
    }
248
249
    /**
250
     * Maps schema data types to EAV's supported types.
251
     *
252
     * @param string $type A schema type. e.g. "string", "integer"
253
     * @return string A EAV type. Possible values are `datetime`, `binary`, `time`,
254
     *  `date`, `float`, `intreger`, `biginteger`, `text`, `string`, `boolean` or
255
     *  `uuid`
256
     */
257
    public function mapType($type)
258
    {
259
        switch ($type) {
260
            case 'float':
261
            case 'decimal':
262
                return 'float';
263
            case 'timestamp':
264
                return 'datetime';
265
            default:
266
                return $type;
267
        }
268
    }
269
}
270