Passed
Push — release/2.5.2 ( bd9268 )
by Sebastian
03:30 queued 01:02
created

Group   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Test Coverage

Coverage 93.44%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 64
c 1
b 0
f 0
dl 0
loc 161
ccs 57
cts 61
cp 0.9344
rs 9.68
wmc 34

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getDelimiter() 0 3 1
A __construct() 0 11 2
A formatting() 0 21 6
A hasDelimiter() 0 3 1
D render() 0 54 23
A getParent() 0 3 1
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 100
    public function __construct(SimpleXMLElement $node, $parent)
72
    {
73 100
        $this->parent = $parent;
74 100
        $this->children = new ArrayList();
75 100
        foreach ($node->children() as $child) {
76 100
            $this->children->append(Factory::create($child, $this));
77
        }
78 100
        $this->initDisplayAttributes($node);
79 100
        $this->initAffixesAttributes($node);
80 100
        $this->initDelimiterAttributes($node);
81 100
        $this->initFormattingAttributes($node);
82 100
    }
83
84
    /**
85
     * @param  $data
86
     * @param  int|null $citationNumber
87
     * @return string
88
     */
89 94
    public function render($data, $citationNumber = null)
90
    {
91 94
        $textParts = [];
92 94
        $terms = $variables = $haveVariables = $elementCount = 0;
93 94
        foreach ($this->children as $child) {
94 94
            $elementCount++;
95
96 94
            if (($child instanceof Text)
97 74
                && ($child->getSource() == 'term'
98 94
                || $child->getSource() == 'value')
99
            ) {
100 34
                ++$terms;
101
            }
102
103 94
            if (($child instanceof Label)) {
104 16
                ++$terms;
105
            }
106 94
            if (method_exists($child, "getSource") && $child->getSource() == 'variable'
107 94
                && !empty($child->getVariable()) && $child->getVariable() != "date"
108 94
                && !empty($data->{$child->getVariable()})
109
            ) {
110 45
                ++$variables;
111
            }
112
113 94
            $text = $child->render($data, $citationNumber);
114 94
            $delimiter = $this->delimiter;
115 94
            if (!empty($text)) {
116 93
                if ($delimiter && ($elementCount < count($this->children))) {
117
                    //check to see if the delimiter is already the last character of the text string
118
                    //if so, remove it so we don't have two of them when the group will be merged
119 85
                    $stext = strip_tags(trim($text));
120 85
                    if ((strrpos($stext, $delimiter[0]) + 1) == strlen($stext) && strlen($stext) > 1) {
121 16
                        $text = str_replace($stext, '----REPLACE----', $text);
122 16
                        $stext = substr($stext, 0, -1);
123 16
                        $text = str_replace('----REPLACE----', $stext, $text);
124
                    }
125
                }
126 93
                $textParts[] = $text;
127
128 93
                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...
129 91
                    || (method_exists(
130 91
                        $child,
131 91
                        "getVariable"
132 93
                    ) && $child->getVariable() != "date" && !empty($child->getVariable()))
133
                ) {
134 82
                    $haveVariables++;
135
                }
136
137 93
                if (method_exists($child, "getSource") && $child->getSource() == 'macro') {
138 51
                    $haveVariables++;
139
                }
140
            }
141
        }
142 94
        return $this->formatting($textParts, $variables, $haveVariables, $terms);
143
    }
144
145
    /**
146
     * @return mixed
147
     */
148
    public function getParent()
149
    {
150
        return $this->parent;
151
    }
152
153
    /**
154
     * @param  $textParts
155
     * @param  $variables
156
     * @param  $haveVariables
157
     * @param  $terms
158
     * @return string
159
     */
160 94
    protected function formatting($textParts, $variables, $haveVariables, $terms)
161
    {
162 94
        if (empty($textParts)) {
163 32
            return "";
164
        }
165
166 93
        if ($variables && !$haveVariables) {
167
            return ""; // there has to be at least one other none empty value before the term is output
168
        }
169
170 93
        if (count($textParts) == $terms) {
171 22
            return ""; // there has to be at least one other none empty value before the term is output
172
        }
173
174 91
        $text = StringHelper::implodeAndPreventConsecutiveChars($this->delimiter, $textParts);
175
176 91
        if (!empty($text)) {
177 91
            return $this->wrapDisplayBlock($this->addAffixes($this->format(($text))));
178
        }
179
180
        return "";
181
    }
182
183
    /**
184
     * @return bool
185
     */
186 31
    public function hasDelimiter()
187
    {
188 31
        return !empty($this->delimiter);
189
    }
190
191
    /**
192
     * @return string
193
     */
194 86
    public function getDelimiter()
195
    {
196 86
        return $this->delimiter;
197
    }
198
}
199