Passed
Push — new-api ( 18d26d...074931 )
by Sebastian
04:59
created

ChooseIf::factory()   A

Complexity

Conditions 5
Paths 12

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 12
c 0
b 0
f 0
nc 12
nop 2
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 5
rs 9.5555
1
<?php
2
declare(strict_types=1);
3
/*
4
 * citeproc-php
5
 *
6
 * @link        http://github.com/seboettg/citeproc-php for the source repository
7
 * @copyright   Copyright (c) 2016 Sebastian Böttger.
8
 * @license     https://opensource.org/licenses/MIT
9
 */
10
11
namespace Seboettg\CiteProc\Rendering\Choose;
12
13
use Seboettg\CiteProc\Constraint\Constraint;
14
use Seboettg\CiteProc\Constraint\Factory;
15
use Seboettg\CiteProc\Data\DataList;
16
use Seboettg\CiteProc\Exception\ClassNotFoundException;
17
use Seboettg\CiteProc\Exception\InvalidStylesheetException;
18
use Seboettg\CiteProc\Rendering\Group;
19
use Seboettg\CiteProc\Rendering\HasParent;
20
use Seboettg\CiteProc\Rendering\Rendering;
21
use Seboettg\Collection\ArrayList;
22
use Seboettg\Collection\ArrayList\ArrayListInterface;
23
use SimpleXMLElement;
24
25
/**
26
 * Class ChooseIf
27
 * @package Seboettg\CiteProc\Node\Choose
28
 */
29
class ChooseIf implements Rendering, HasParent
30
{
31
    /**
32
     * @var ArrayList<Constraint>
33
     */
34
    private $constraints;
35
36
    /**
37
     * @var ArrayList
38
     */
39
    protected $children;
40
41
    /**
42
     * @var string
43
     */
44
    private $match;
45
46
    /**
47
     * @var
48
     */
49
    protected $parent;
50
51
    /**
52
     * @param SimpleXMLElement|null $node
53
     * @param Choose $parent
54
     * @return ChooseIf|ChooseElse|ChooseElseIf
55
     * @throws ClassNotFoundException
56
     * @throws InvalidStylesheetException
57
     */
58 63
    public static function factory(?SimpleXMLElement $node, Choose $parent): ChooseIf
59
    {
60 63
        $constraints = new ArrayList();
61 63
        $children = new ArrayList();
62 63
        $match = (string) $node['match'];
63 63
        if (empty($match)) {
64 62
            $match = Constraint::MATCH_ALL;
65
        }
66 63
        foreach ($node->attributes() as $name => $value) {
0 ignored issues
show
Bug introduced by
The method attributes() does not exist on null. ( Ignorable by Annotation )

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

66
        foreach ($node->/** @scrutinizer ignore-call */ attributes() as $name => $value) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
67 63
            if ('match' !== $name) {
68 63
                $constraints->append(Factory::createConstraint((string) $name, (string) $value, $match));
69
            }
70
        }
71 63
        $chooseIf = new self($constraints, $children, $match, $parent);
72 63
        foreach ($node->children() as $child) {
73 63
            $children->append(Factory::create($child, $chooseIf));
74
        }
75 63
        return $chooseIf;
76
    }
77
78 63
    public function __construct(ArrayListInterface $constraints, ArrayListInterface $children, string $match, $parent)
79
    {
80 63
        $this->constraints = $constraints;
0 ignored issues
show
Documentation Bug introduced by
$constraints is of type Seboettg\Collection\ArrayList\ArrayListInterface, but the property $constraints was declared to be of type Seboettg\Collection\ArrayList. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
81 63
        $this->children = $children;
0 ignored issues
show
Documentation Bug introduced by
$children is of type Seboettg\Collection\ArrayList\ArrayListInterface, but the property $children was declared to be of type Seboettg\Collection\ArrayList. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
82 63
        $this->match = $match;
83 63
        $this->parent = $parent;
84 63
    }
85
86
    /**
87
     * @param array|DataList $data
88
     * @param null|int $citationNumber
89
     * @return string
90
     */
91 56
    public function render($data, $citationNumber = null): string
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$citationNumber" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$citationNumber"; expected 0 but found 1
Loading history...
92
    {
93 56
        $ret = [];
94
        /** @var Rendering $child */
95 56
        foreach ($this->children as $child) {
96 56
            $ret[] = $child->render($data, $citationNumber);
97
        }
98 56
        $glue = "";
99 56
        $parent = $this->parent->getParent();
100 56
        if ($parent instanceof Group && $parent->hasDelimiter()) {
101 23
            $glue = $parent->getDelimiter();
102
        }
103 56
        return implode($glue, array_filter($ret));
104
    }
105
    /**
106
     * @param $data
107
     * @param null|int $citationNumber
108
     * @return bool
109
     */
110 56
    public function match($data, $citationNumber = null): bool
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$citationNumber" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$citationNumber"; expected 0 but found 1
Loading history...
111
    {
112 56
        if ($this->constraints->count() === 1) {
113 56
            return $this->constraints->current()->validate($data);
114
        }
115 19
        $result = true;
116
        /** @var Constraint $constraint */
117 19
        foreach ($this->constraints as $constraint) {
118 19
            if ($this->match === Constraint::MATCH_ANY) {
119 11
                if ($constraint->validate($data, $citationNumber)) {
120 11
                    return true;
121
                }
122
            } else {
123 19
                $result &= $constraint->validate($data, $citationNumber);
124
            }
125
        }
126 19
        if ($this->constraints->count() > 1 && $this->match === Constraint::MATCH_ALL) {
127 18
            return (bool) $result;
128 12
        } elseif ($this->match === Constraint::MATCH_NONE) {
129 3
            return !((bool) $result);
130
        }
131 11
        return false;
132
    }
133
134
135
    /**
136
     * @noinspection PhpUnused
137
     * @return Choose
138
     */
139
    public function getParent(): Choose
140
    {
141
        return $this->parent;
142
    }
143
144
    public function setParent($parent)
145
    {
146
        $this->parent = $parent;
147
    }
148
}
149