Completed
Pull Request — 4.0 (#59)
by David
05:43
created

WeakrefObjectStorage   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 116
Duplicated Lines 12.07 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 17
c 2
b 0
f 0
lcom 1
cbo 0
dl 14
loc 116
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A set() 0 9 2
A has() 7 12 3
A get() 7 10 3
A remove() 0 4 1
A apply() 0 12 4
A cleanupDanglingWeakRefs() 0 10 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 Copyright (C) 2006-2014 David Négrier - THE CODING MACHINE
5
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
*/
20
21
namespace Mouf\Database\TDBM;
22
23
/**
24
 * The WeakrefObjectStorage class is used to reference all beans that have been fetched from the database.
25
 * If a bean is requested twice from TDBM, the WeakrefObjectStorage is used to "cache" the bean.
26
 * Unlike the StandardObjectStorage, the WeakrefObjectStorage manages memory in a clever way, using the weakref
27
 * PHP extension. It is used if the "weakref" extension is available.
28
 * Otherwise, the StandardObjectStorage is used instead.
29
 *
30
 * @author David Negrier
31
 */
32
class WeakrefObjectStorage
33
{
34
    /**
35
     * An array of fetched object, accessible via table name and primary key.
36
     * If the primary key is split on several columns, access is done by an array of columns, serialized.
37
     *
38
     * @var array<string, WeakMap<string, TDBMObject>>
39
     */
40
    private $objects = array();
41
42
    /**
43
     * Every 10000 set in the dataset, we perform a cleanup to ensure the WeakRef instances
44
     * are removed if they are no more valid.
45
     * This is to avoid having memory used by dangling WeakRef instances.
46
     *
47
     * @var int
48
     */
49
    private $garbageCollectorCount = 0;
50
51
    /**
52
     * Sets an object in the storage.
53
     *
54
     * @param string $tableName
55
     * @param string $id
56
     * @param DbRow  $dbRow
57
     */
58
    public function set($tableName, $id, DbRow $dbRow)
59
    {
60
        $this->objects[$tableName][$id] = new \WeakRef($dbRow);
61
        ++$this->garbageCollectorCount;
62
        if ($this->garbageCollectorCount == 10000) {
63
            $this->garbageCollectorCount = 0;
64
            $this->cleanupDanglingWeakRefs();
65
        }
66
    }
67
68
    /**
69
     * Checks if an object is in the storage.
70
     *
71
     * @param string $tableName
72
     * @param string $id
73
     *
74
     * @return bool
75
     */
76
    public function has($tableName, $id)
77
    {
78 View Code Duplication
        if (isset($this->objects[$tableName][$id])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
79
            if ($this->objects[$tableName][$id]->valid()) {
80
                return true;
81
            } else {
82
                unset($this->objects[$tableName][$id]);
83
            }
84
        }
85
86
        return false;
87
    }
88
89
    /**
90
     * Returns an object from the storage (or null if no object is set).
91
     *
92
     * @param string $tableName
93
     * @param string $id
94
     *
95
     * @return DbRow
96
     */
97
    public function get($tableName, $id)
98
    {
99 View Code Duplication
        if (isset($this->objects[$tableName][$id])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
            if ($this->objects[$tableName][$id]->valid()) {
101
                return $this->objects[$tableName][$id]->get();
102
            }
103
        } else {
104
            return;
105
        }
106
    }
107
108
    /**
109
     * Removes an object from the storage.
110
     *
111
     * @param string $tableName
112
     * @param string $id
113
     */
114
    public function remove($tableName, $id)
115
    {
116
        unset($this->objects[$tableName][$id]);
117
    }
118
119
    /**
120
     * Applies the callback to all objects.
121
     *
122
     * @param callable $callback
123
     */
124
    public function apply(callable $callback)
125
    {
126
        foreach ($this->objects as $tableName => $table) {
127
            foreach ($table as $id => $obj) {
128
                if ($obj->valid()) {
129
                    $callback($obj->get(), $tableName, $id);
130
                } else {
131
                    unset($this->objects[$tableName][$id]);
132
                }
133
            }
134
        }
135
    }
136
137
    private function cleanupDanglingWeakRefs()
138
    {
139
        foreach ($this->objects as $tableName => $table) {
140
            foreach ($table as $id => $obj) {
141
                if (!$obj->valid()) {
142
                    unset($this->objects[$tableName][$id]);
143
                }
144
            }
145
        }
146
    }
147
}
148