Passed
Push — master ( c0f43d...08ed67 )
by Julien
05:01
created

Uuid::getBinaryUuid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit\Mvc\Model;
13
14
use Phalcon\Db\RawValue;
15
use Phalcon\Encryption\Security;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Zemit\Mvc\Model\Security. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
16
use Zemit\Mvc\Model\AbstractTrait\AbstractBehavior;
17
use Zemit\Mvc\Model\AbstractTrait\AbstractInjectable;
18
use Zemit\Mvc\Model\Behavior\Transformable;
19
20
trait Uuid
21
{
22
    use AbstractBehavior;
23
    use AbstractInjectable;
24
    use Options;
25
    use Behavior;
26
    
27
    /**
28
     * Initializing Uuid
29
     */
30 2
    public function initializeUuid(?array $options = null): void
31
    {
32 2
        $options ??= $this->getOptionsManager()->get('uuid') ?? [];
33
        
34 2
        $field = $options['field'] ?? 'uuid';
35 2
        $native = $options['native'] ?? true;
36 2
        $binary = $options['binary'] ?? true;
37
        
38 2
        $security = $this->getDI()->get('security');
39 2
        assert($security instanceof Security);
40
        
41 2
        $this->setUuidBehavior(new Transformable([
42 2
            'beforeValidationOnCreate' => [
43 2
                $field => function ($model, $field) use ($security, $native, $binary) {
44
                    return $model->getAttribute($field) ?? $native
45
                        ? ($binary
46
                            ? new RawValue('UUID_TO_BIN(UUID())')
47
                            : new RawValue('UUID()')
48
                        )
49
                        : ($binary
50
                            ? $this->getBinaryUuid($security->getRandom()->uuid())
51
                            : $security->getRandom()->uuid()
52
                        );
53 2
                },
54 2
            ],
55 2
            'afterFetch' => [
56 2
                $field => function ($model, $field) use ($binary) {
57
                    // $native not yet supported while fetching
58
                    $value = $model->getAttribute($field);
59
                    if ($binary && !empty($value)) {
60
                        $hex = bin2hex($value);
61
                        $uuid = sprintf(
62
                            '%s-%s-%s-%s-%s',
63
                            substr($hex, 0, 8),
64
                            substr($hex, 8, 4),
65
                            substr($hex, 12, 4),
66
                            substr($hex, 16, 4),
67
                            substr($hex, 20, 12)
68
                        );
69
                        $this->setAttribute($field, $uuid);
0 ignored issues
show
Bug introduced by
It seems like setAttribute() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

69
                        $this->/** @scrutinizer ignore-call */ 
70
                               setAttribute($field, $uuid);
Loading history...
70
                        return $uuid;
71
                    }
72 2
                },
73 2
            ],
74 2
        ]));
75
    }
76
    
77
    /**
78
     * Get a binary representation of UUID
79
     *
80
     * @param string $uuid
81
     * @return string
82
     */
83
    private function getBinaryUuid($uuid)
84
    {
85
        return pack('h*', str_replace('-', '', $uuid));
86
    }
87
    
88
    /**
89
     * Set Uuid Behavior
90
     */
91 2
    public function setUuidBehavior(Transformable $uuidBehavior): void
92
    {
93 2
        $this->setBehavior('uuid', $uuidBehavior);
94
    }
95
    
96
    /**
97
     * Get Uuid Behavior
98
     */
99
    public function getUuidBehavior(): Transformable
100
    {
101
        $behavior = $this->getBehavior('uuid');
102
        assert($behavior instanceof Transformable);
103
        return $behavior;
104
    }
105
}
106