Passed
Push — new-api ( 42b595...e6ef7d )
by Sebastian
05:57
created

Group   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Test Coverage

Coverage 96.61%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 62
c 1
b 0
f 0
dl 0
loc 158
ccs 57
cts 59
cp 0.9661
rs 9.76
wmc 33

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getParent() 0 3 1
A __construct() 0 11 2
A getDelimiter() 0 3 1
A formatting() 0 21 6
A hasDelimiter() 0 3 1
D render() 0 51 22
1
<?php
2
/*
3
 * citeproc-php
4
 *
5
 * @link        http://github.com/seboettg/citeproc-php for the source repository
6
 * @copyright   Copyright (c) 2016 Sebastian Böttger.
7
 * @license     https://opensource.org/licenses/MIT
8
 */
9
10
namespace Seboettg\CiteProc\Rendering;
11
12
use Seboettg\CiteProc\Exception\InvalidStylesheetException;
13
use Seboettg\CiteProc\Styles\AffixesTrait;
14
use Seboettg\CiteProc\Styles\ConsecutivePunctuationCharacterTrait;
15
use Seboettg\CiteProc\Styles\DelimiterTrait;
16
use Seboettg\CiteProc\Styles\DisplayTrait;
17
use Seboettg\CiteProc\Styles\FormattingTrait;
18
use Seboettg\CiteProc\Util\Factory;
19
use Seboettg\CiteProc\Util\StringHelper;
20
use Seboettg\Collection\ArrayList;
21
use SimpleXMLElement;
22
23
/**
24
 * Class Group
25
 * The cs:group rendering element must contain one or more rendering elements (with the exception of cs:layout).
26
 * cs:group may carry the delimiter attribute to separate its child elements, as well as affixes and display attributes
27
 * (applied to the output of the group as a whole) and formatting attributes (transmitted to the enclosed elements).
28
 * cs:group implicitly acts as a conditional: cs:group and its child elements are suppressed if a) at least one
29
 * rendering element in cs:group calls a variable (either directly or via a macro), and b) all variables that are
30
 * called are empty. This accommodates descriptive cs:text elements.
31
 *
32
 * @package Seboettg\CiteProc\Rendering
33
 *
34
 * @author Sebastian Böttger <[email protected]>
35
 */
36
class Group implements Rendering, HasParent
37
{
38
    use DelimiterTrait,
0 ignored issues
show
Bug introduced by
The trait Seboettg\CiteProc\Styles\AffixesTrait requires the property $single which is not provided by Seboettg\CiteProc\Rendering\Group.
Loading history...
39
        AffixesTrait,
40
        DisplayTrait,
41
        FormattingTrait,
42
        ConsecutivePunctuationCharacterTrait;
43
44
    /**
45
     * @var ArrayList
46
     */
47
    private $children;
48
49
    /**
50
     * cs:group may carry the delimiter attribute to separate its child elements
51
     *
52
     * @var
53
     */
54
    private $delimiter = "";
55
56
    private $parent;
57
58
    /**
59
     * @var array
60
     */
61
    private $renderedChildsWithVariable = [];
62
63
64
    /**
65
     * Group constructor.
66
     *
67
     * @param  SimpleXMLElement $node
68
     * @param  $parent
69
     * @throws InvalidStylesheetException
70
     */
71 90
    public function __construct(SimpleXMLElement $node, $parent)
72
    {
73 90
        $this->parent = $parent;
74 90
        $this->children = new ArrayList();
75 90
        foreach ($node->children() as $child) {
76 90
            $this->children->append(Factory::create($child, $this));
77
        }
78 90
        $this->initDisplayAttributes($node);
79 90
        $this->initAffixesAttributes($node);
80 90
        $this->initDelimiterAttributes($node);
81 90
        $this->initFormattingAttributes($node);
82 90
    }
83
84
    /**
85
     * @param  $data
86
     * @param  int|null $citationNumber
87
     * @return string
88
     */
89 84
    public function render($data, $citationNumber = null)
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...
90
    {
91 84
        $textParts = [];
92 84
        $terms = $variables = $haveVariables = $elementCount = 0;
93 84
        foreach ($this->children as $child) {
94 84
            $elementCount++;
95
96 84
            if (($child instanceof Text) && in_array($child->getSource(), ['term', 'value'])) {
97 30
                ++$terms;
98
            }
99
100 84
            if (($child instanceof Label)) {
101 15
                ++$terms;
102
            }
103 84
            if (method_exists($child, "getSource") && $child->getSource() == 'variable'
104 84
                && !empty($child->getVariable()) && $child->getVariable() != "date"
105 84
                && !empty($data->{$child->getVariable()})
106
            ) {
107 41
                ++$variables;
108
            }
109
110 84
            $text = $child->render($data, $citationNumber);
111 84
            $delimiter = $this->delimiter;
112 84
            if (!empty($text)) {
113 83
                if ($delimiter && ($elementCount < count($this->children))) {
114
                    //check to see if the delimiter is already the last character of the text string
115
                    //if so, remove it so we don't have two of them when the group will be merged
116 75
                    $stext = strip_tags(trim($text));
117 75
                    if ((strrpos($stext, $delimiter[0]) + 1) == strlen($stext) && strlen($stext) > 1) {
118 13
                        $text = str_replace($stext, '----REPLACE----', $text);
119 13
                        $stext = substr($stext, 0, -1);
120 13
                        $text = str_replace('----REPLACE----', $stext, $text);
121
                    }
122
                }
123 83
                $textParts[] = $text;
124
125 83
                if (method_exists($child, "getSource") && $child->getSource() == 'variable'
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (method_exists($child, '...($child->getVariable()), Probably Intended Meaning: method_exists($child, 'g...$child->getVariable()))
Loading history...
126 81
                    || (method_exists(
127 81
                        $child,
128 81
                        "getVariable"
129 83
                    ) && $child->getVariable() != "date" && !empty($child->getVariable()))
130
                ) {
131 72
                    $haveVariables++;
132
                }
133
134 83
                if (method_exists($child, "getSource") && $child->getSource() == 'macro') {
135 84
                    $haveVariables++;
136
                }
137
            }
138
        }
139 84
        return $this->formatting($textParts, $variables, $haveVariables, $terms);
140
    }
141
142
    /**
143
     * @return mixed
144
     */
145 11
    public function getParent()
146
    {
147 11
        return $this->parent;
148
    }
149
150
    /**
151
     * @param  $textParts
152
     * @param  $variables
153
     * @param  $haveVariables
154
     * @param  $terms
155
     * @return string
156
     */
157 84
    protected function formatting($textParts, $variables, $haveVariables, $terms)
158
    {
159 84
        if (empty($textParts)) {
160 26
            return "";
161
        }
162
163 83
        if ($variables && !$haveVariables) {
164
            return ""; // there has to be at least one other none empty value before the term is output
165
        }
166
167 83
        if (count($textParts) == $terms) {
168 18
            return ""; // there has to be at least one other none empty value before the term is output
169
        }
170
171 81
        $text = StringHelper::implodeAndPreventConsecutiveChars($this->delimiter, $textParts);
172
173 81
        if (!empty($text)) {
174 81
            return $this->wrapDisplayBlock($this->addAffixes($this->format(($text))));
175
        }
176
177
        return "";
178
    }
179
180
    /**
181
     * @return bool
182
     */
183 25
    public function hasDelimiter()
184
    {
185 25
        return !empty($this->delimiter);
186
    }
187
188
    /**
189
     * @return string
190
     */
191 76
    public function getDelimiter()
192
    {
193 76
        return $this->delimiter;
194
    }
195
}
196