Completed
Push — master ( fd62a8...5cbc9e )
by Filipe
04:02
created

BelongsTo::getFieldsPrefixed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 12
ccs 0
cts 11
cp 0
rs 9.4285
cc 2
eloc 8
nc 2
nop 0
crap 6
1
<?php
2
3
/**
4
 * This file is part of slick/orm package
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Orm\Mapper\Relation;
11
12
use Slick\Common\Base;
13
use Slick\Common\Utils\Text;
14
use Slick\Orm\Descriptor\EntityDescriptorInterface;
15
use Slick\Orm\Descriptor\EntityDescriptorRegistry;
16
use Slick\Orm\Descriptor\Field\FieldDescriptor;
17
use Slick\Orm\Event\Select;
18
use Slick\Orm\Mapper\RelationInterface;
19
use Slick\Orm\Orm;
20
21
/**
22
 * BelongsTo (Many-To-On) relation
23
 *
24
 * @package Slick\Orm\Mapper\Relation
25
 * @author  Filipe Silva <[email protected]>
26
 */
27
class BelongsTo extends Base implements RelationInterface
28
{
29
30
    /**
31
     * @readwrite
32
     * @var string
33
     */
34
    protected $property;
35
36
    /**
37
     * @readwrite
38
     * @var EntityDescriptorInterface
39
     */
40
    protected $entityDescriptor;
41
42
    /**
43
     * @readwrite
44
     * @var string
45
     */
46
    protected $parentEntity;
47
48
    /**
49
     * @readwrite
50
     * @var EntityDescriptorInterface
51
     */
52
    protected $parentEntityDescriptor;
53
54
    /**
55
     * @readwrite
56
     * @var string
57
     */
58
    protected $foreignKey;
59
60
    public function __construct($options)
61
    {
62
        /** @var \Slick\Orm\Annotations\BelongsTo $annotation */
63
        $annotation = $options['annotation'];
64
        unset($options['annotation']);
65
        $options['foreignKey'] = $annotation->getParameter('foreignKey');
66
        $options['parentEntity'] = $annotation->getValue();
67
        parent::__construct($options);
68
69
        $this->registerListeners();
70
    }
71
72
    /**
73
     * Sets the parent entity descriptor object
74
     *
75
     * @return EntityDescriptorInterface
76
     */
77
    public function getParentEntityDescriptor()
78
    {
79
        if (is_null($this->parentEntityDescriptor)) {
80
            $this->setParentEntityDescriptor(
81
                EntityDescriptorRegistry::getInstance()
82
                    ->getDescriptorFor($this->parentEntity)
83
            );
84
        }
85
        return $this->parentEntityDescriptor;
86
    }
87
88
    /**
89
     * Gets foreign key name
90
     *
91
     * @return string
92
     */
93
    public function getForeignKey()
94
    {
95
        if (is_null($this->foreignKey)) {
96
            $name = $this->getParentEntityDescriptor()->getTableName();
97
            $name = Text::singular(strtolower($name));
98
            $this->foreignKey = "{$name}_id";
99
        }
100
        return $this->foreignKey;
101
    }
102
103
    /**
104
     * Sets parent entity descriptor
105
     *
106
     * @param EntityDescriptorInterface $parentEntityDescriptor
107
     * @return BelongsTo
108
     */
109
    public function setParentEntityDescriptor
110
    (EntityDescriptorInterface $parentEntityDescriptor
111
    ) {
112
        $this->parentEntityDescriptor = $parentEntityDescriptor;
113
        return $this;
114
    }
115
116
    public function beforeSelect(Select $event)
117
    {
118
        $fields = $this->getFieldsPrefixed();
119
        $table = $this->entityDescriptor->getTableName();
120
        $relateTable = $this->getParentEntityDescriptor()->getTableName();
121
        $pmk = $this->getParentEntityDescriptor()->getPrimaryKey()->getField();
122
        $onClause = "{$table}.{$this->getForeignKey()} = {$relateTable}.{$pmk}";
123
        $query = $event->getQuery();
124
        $query->join($relateTable, $onClause, $fields, $relateTable);
125
    }
126
127
    public function afterSelect(Select $event)
128
    {
129
        foreach ($event->getEntityCollection() as $index => $entity) {
130
            $row = $event->getData()[$index];
131
            $entity->{$this->property} = $this->map($row);
132
        }
133
    }
134
135
    /**
136
     * Registers the listener for before select event
137
     */
138
    private function registerListeners()
139
    {
140
        Orm::addListener(
141
            $this->entityDescriptor->className(),
142
            Select::ACTION_BEFORE_SELECT,
143
            [$this, 'beforeSelect']
144
        );
145
146
        Orm::addListener(
147
            $this->entityDescriptor->className(),
148
            Select::ACTION_AFTER_SELECT,
149
            [$this, 'afterSelect']
150
        );
151
    }
152
153
    /**
154
     * Prefixed fields for join
155
     *
156
     * @return array
157
     */
158
    private function getFieldsPrefixed()
159
    {
160
        $fields = $this->getParentEntityDescriptor()->getFields();
161
        $table = $this->getParentEntityDescriptor()->getTableName();
162
        $data = [];
163
        /** @var FieldDescriptor $field */
164
        foreach ($fields as $field) {
165
            $data[] = "{$field->getField()} AS ".
166
                "{$table}_{$field->getField()}";
167
        }
168
        return $data;
169
    }
170
171
    private function map($dataRow)
172
    {
173
        $relateTable = $this->getParentEntityDescriptor()->getTableName();
174
        $regexp = "/{$relateTable}_(?P<name>.+)/i";
175
        $data = [];
176
        foreach ($dataRow as $field => $value) {
177
            if (preg_match($regexp, $field, $matched)) {
178
                $data[$matched['name']] = $value;
179
            }
180
        }
181
        return Orm::getRepository($this->parentEntity)
182
            ->getEntityMapper()
183
            ->createFrom($data);
184
    }
185
186
}