One2Many::onParentSave()   B
last analyzed

Complexity

Conditions 8
Paths 8

Size

Total Lines 55
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 11
Bugs 2 Features 0
Metric Value
c 11
b 2
f 0
dl 0
loc 55
rs 7.4033
cc 8
eloc 34
nc 8
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Fwk
4
 *
5
 * Copyright (c) 2011-2014, Julien Ballestracci <[email protected]>.
6
 * All rights reserved.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
15
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
17
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
21
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22
 * POSSIBILITY OF SUCH DAMAGE.
23
 *
24
 * PHP Version 5.3
25
 *
26
 * @category   Database
27
 * @package    Fwk
28
 * @subpackage Db
29
 * @author     Julien Ballestracci <[email protected]>
30
 * @copyright  2011-2014 Julien Ballestracci <[email protected]>
31
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
32
 * @link       http://www.nitronet.org/fwk
33
 */
34
namespace Fwk\Db\Relations;
35
36
use Fwk\Db\Events\AbstractEntityEvent;
37
use Fwk\Db\Events\AfterSaveEvent;
38
use Fwk\Db\Events\AfterUpdateEvent;
39
use Fwk\Db\RelationInterface;
40
use Fwk\Db\Query;
41
use Fwk\Db\Accessor;
42
use Fwk\Db\Registry\Registry;
43
use Fwk\Db\Workers\SaveEntityWorker;
44
use Fwk\Db\Workers\DeleteEntityWorker;
45
use Fwk\Events\Dispatcher;
46
47
/**
48
 * One to Many RelationInterface
49
 *
50
 * Represents a 1-n relation in the database
51
 *
52
 * @category Relations
53
 * @package  Fwk\Db
54
 * @author   Julien Ballestracci <[email protected]>
55
 * @license  http://www.opensource.org/licenses/bsd-license.php  BSD License
56
 * @link     http://www.nitronet.org/fwk
57
 */
58
class One2Many extends AbstractManyRelation implements RelationInterface
59
{
60
    /**
61
     * Prepares a Query to fetch this relation (if FETCH_EAGER)
62
     *
63
     * @param Query  $query      The running Query
64
     * @param string $columnName The column name (property) for this relation
65
     *
66
     * @return void
67
     */
68
    public function prepare(Query $query, $columnName)
69
    {
70
        if ($this->isLazy()) {
71
            return;
72
        }
73
74
        $this->columnName   = $columnName;
75
        $join = array(
76
            'column' => $this->columnName,
77
            'relation' => $this,
78
            'skipped' => false,
79
            'reference' => $this->reference,
80
            'entity' => $this->entity
81
        );
82
83
        $query->join(
84
            $this->tableName,
85
            $this->local,
86
            $this->foreign,
87
            Query::JOIN_LEFT,
88
            $join
89
        );
90
    }
91
92
    /**
93
     * Fetches data from the database an fills this relation
94
     *
95
     * @return RelationInterface
96
     */
97
    public function fetch()
98
    {
99
        if (!$this->fetched && $this->isActive()) {
100
            $query = new Query();
101
            $query->entity($this->getEntity())
102
                ->select()
103
                ->from($this->getTableName(), 'lazy')
104
                ->where('lazy.' . $this->getForeign() . '=?');
105
106
            if (isset($this->orderBy)) {
107
                $query->orderBy(
108
                    $this->orderBy['column'],
109
                    $this->orderBy['direction']
110
                );
111
            }
112
113
            $connect   = $this->getConnection();
114
            $res    = $connect->execute($query, array($this->parentRefs));
115
            $idKeys = $connect->table($this->getTableName())->getIdentifiersKeys();
116
            foreach ($res as $result) {
117
                $ids     = array();
118
                $access  = new Accessor($result);
119
                foreach ($idKeys as $key) {
120
                    $ids[$key]   = $access->get($key);
121
                }
122
                parent::add($result, $ids);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (add() instead of fetch()). Are you sure this is correct? If so, you might want to change this to $this->add().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
123
            }
124
125
            $this->setFetched(true);
126
        }
127
128
        return $this;
129
    }
130
131
    /**
132
     * Defines a parent entity for this relation
133
     *
134
     * @param object     $object The parent entity
135
     * @param Dispatcher $evd    The related events dispatcher
136
     *
137
     * @return boolean
138
     */
139
    public function setParent($object, Dispatcher $evd)
140
    {
141
        $return     = parent::setParent($object, $evd);
142
        if ($return === true) {
143
            $evd->on(AfterSaveEvent::EVENT_NAME, array($this, 'onParentSave'));
144
            $evd->on(AfterUpdateEvent::EVENT_NAME, array($this, 'onParentSave'));
145
        }
146
147
        return $return;
148
    }
149
150
    /**
151
     * Listener executed when parent entity is saved
152
     *
153
     * @param AbstractEntityEvent $event The EntityEvent
154
     *
155
     * @return void
156
     */
157
    public function onParentSave(AbstractEntityEvent $event)
158
    {
159
        $connection     = $event->getConnection();
160
        $parentRegistry = $event->getTable()->getRegistry();
161
        $table          = $connection->table($this->getTableName());
162
        $registry       = $table->getRegistry();
163
164
        foreach ($this->getWorkersQueue() as $worker) {
165
            $worker->setRegistry($registry);
166
            $entity     = $worker->getEntity();
167
168
            if ($worker instanceof SaveEntityWorker) {
169
                if (!isset($this->parent)) {
170
                    throw new \RuntimeException(
171
                        sprintf(
172
                            'No parent defined for entity %s',
173
                            get_class($entity)
174
                        )
175
                    );
176
                }
177
178
                $access     = new Accessor($this->parent);
179
                $entry      = $parentRegistry->getEntry($this->parent);
180
                $ids        = $entry->getIdentifiers();
181
                if (!count($ids)) {
182
                    throw new \RuntimeException(
183
                        sprintf(
184
                            'Parent (%s) have no identifiers defined',
185
                            get_class($this->parent)
186
                        )
187
                    );
188
                }
189
190
                if (count($ids) > 1 && !array_key_exists($this->local, $ids)) {
191
                    throw new \RuntimeException(
192
                        sprintf(
193
                            'Local key "%s" is not a valid identifier (primary key on %s)',
194
                            $this->local,
195
                            $registry->getTableName()
196
                        )
197
                    );
198
                }
199
200
                $value  = $access->get($this->local);
201
                Accessor::factory($entity)->set($this->foreign, $value);
202
                $registry->markForAction($entity, Registry::ACTION_SAVE);
203
            }
204
205
            $worker->execute($connection);
206
207
            if ($worker instanceof DeleteEntityWorker) {
208
                parent::getRegistry()->remove($entity);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getRegistry() instead of onParentSave()). Are you sure this is correct? If so, you might want to change this to $this->getRegistry().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
209
            }
210
        }
211
    }
212
}
213