Completed
Push — master ( 5a7e4d...40d001 )
by Sebastian
04:05
created

Group::doesRendersEmptyVariable()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
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\Styles\AffixesTrait;
13
use Seboettg\CiteProc\Styles\ConsecutivePunctuationCharacterTrait;
14
use Seboettg\CiteProc\Styles\DelimiterTrait;
15
use Seboettg\CiteProc\Styles\DisplayTrait;
16
use Seboettg\CiteProc\Styles\FormattingTrait;
17
use Seboettg\CiteProc\Util\Factory;
18
use Seboettg\Collection\ArrayList;
19
20
21
/**
22
 * Class Group
23
 * The cs:group rendering element must contain one or more rendering elements (with the exception of cs:layout).
24
 * cs:group may carry the delimiter attribute to separate its child elements, as well as affixes and display attributes
25
 * (applied to the output of the group as a whole) and formatting attributes (transmitted to the enclosed elements).
26
 * cs:group implicitly acts as a conditional: cs:group and its child elements are suppressed if a) at least one
27
 * rendering element in cs:group calls a variable (either directly or via a macro), and b) all variables that are
28
 * called are empty. This accommodates descriptive cs:text elements.
29
 *
30
 * @package Seboettg\CiteProc\Rendering
31
 *
32
 * @author Sebastian Böttger <[email protected]>
33
 */
34
class Group implements Rendering, HasParent, RendersEmptyVariables
35
{
36
    use DelimiterTrait,
37
        AffixesTrait,
38
        DisplayTrait,
39
        FormattingTrait,
40
        ConsecutivePunctuationCharacterTrait,
41
        RendersEmptyVariablesTrait;
42
43
    const CLASS_PATH = 'Seboettg\CiteProc\Rendering';
44
45
    private static $suppressableElements = [
0 ignored issues
show
Unused Code introduced by
The property $suppressableElements is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
46
        self::CLASS_PATH . '\Number',
47
        self::CLASS_PATH . '\Group',
48
        self::CLASS_PATH . '\Date\Date',
49
        self::CLASS_PATH . '\Choose\Choose'
50
    ]; 
51
52
    /**
53
     * @var ArrayList
54
     */
55
    private $children;
56
57
    /**
58
     * cs:group may carry the delimiter attribute to separate its child elements
59
     * @var
60
     */
61
    private $delimiter = "";
62
63
    private $parent;
64
65
    /**
66
     * @var array
67
     */
68
    private $renderedChildsWithVariable = [];
0 ignored issues
show
Unused Code introduced by
The property $renderedChildsWithVariable is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
69
70
71 View Code Duplication
    public function __construct(\SimpleXMLElement $node, $parent)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
72
    {
73
        $this->parent = $parent;
74
        $this->children = new ArrayList();
75
        foreach ($node->children() as $child) {
76
            $this->children->append(Factory::create($child, $this));
77
        }
78
        $this->initDisplayAttributes($node);
79
        $this->initAffixesAttributes($node);
80
        $this->initDelimiterAttributes($node);
81
        $this->initFormattingAttributes($node);
82
    }
83
84
    /**
85
     * @param $data
86
     * @param int|null $citationNumber
87
     * @return string
88
     */
89
    public function render($data, $citationNumber = null)
90
    {
91
        $textParts = array();
92
        $terms = $variables = $haveVariables = $elementCount = 0;
93
        foreach ($this->children as $child) {
94
            $elementCount++;
95
96
            if (($child instanceof Text) &&
97
                ($child->getSource() == 'term' ||
98
                    $child->getSource() == 'value')) {
99
                ++$terms;
100
            }
101
102
            if (($child instanceof Label)) {
103
                ++$terms;
104
            }
105
            if (method_exists($child, "getSource") && $child->getSource() == 'variable' &&
106
                !empty($child->getVariable()) && $child->getVariable() != "date" &&
107
                !empty($data->{$child->getVariable()})
108
            ) {
109
                ++$variables;
110
            }
111
112
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
113
            if (method_exists($child, "getSource") && $child->getSource() == 'macro') {
114
                //if ($this->doesRendersEmptyVariable($child, $data)) {
115
                    ++$variables;
116
                //}
117
            }
118
            */
119
120
            $text = $child->render($data, $citationNumber);
121
            $delimiter = $this->delimiter;
122
            if (!empty($text)) {
123
                if ($delimiter && ($elementCount < count($this->children))) {
124
                    //check to see if the delimiter is already the last character of the text string
125
                    //if so, remove it so we don't have two of them when the group will be merged
126
                    $stext = strip_tags(trim($text));
127
                    if ((strrpos($stext, $delimiter[0]) + 1) == strlen($stext) && strlen($stext) > 1) {
128
                        $text = str_replace($stext, '----REPLACE----', $text);
129
                        $stext = substr($stext, 0, -1);
130
                        $text = str_replace('----REPLACE----', $stext, $text);
131
                    }
132
                }
133
                $textParts[] = $text;
134
135
                if (method_exists($child, "getSource") && $child->getSource() == 'variable' ||
136
                   (method_exists($child, "getVariable") && $child->getVariable() != "date" && !empty($child->getVariable()))) {
137
138
                    $haveVariables++;
139
                }
140
141
                if (method_exists($child, "getSource") && $child->getSource() == 'macro') {
142
                    $haveVariables++;
143
                }
144
            }
145
        }
146
        return $this->formatting($textParts, $variables, $haveVariables, $terms);
147
    }
148
149
    /**
150
     * cs:group implicitly acts as a conditional: cs:group and its child elements are suppressed if a) at least one
151
     * rendering element in cs:group calls a variable (either directly or via a macro), and b) all variables that are
152
     * called are empty. This accommodates descriptive cs:text elements. For example,
153
     * @param $child
154
     * @param $data
155
     * @return bool
156
     */
157
    private function doesRendersEmptyVariable($child, $data)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
158
    {
159
        if ($child instanceof RendersEmptyVariables/*Text || $child instanceof Choose*/) {
160
            return $child->rendersEmptyVariables($data);
161
        }
162
163
        return false;
164
    }
165
166
    /**
167
     * @return mixed
168
     */
169
    public function getParent()
170
    {
171
        return $this->parent;
172
    }
173
174
    /**
175
     * @param $textParts
176
     * @param $variables
177
     * @param $haveVariables
178
     * @param $terms
179
     * @return string
180
     */
181
    protected function formatting($textParts, $variables, $haveVariables, $terms)
182
    {
183
        if (empty($textParts)) {
184
            return "";
185
        }
186
187
        if ($variables && $haveVariables < 1) {
188
            return ""; // there has to be at least one other none empty value before the term is output
189
        }
190
191
        if (count($textParts) == $terms) {
192
            return ""; // there has to be at least one other none empty value before the term is output
193
        }
194
195
        $text = implode($this->delimiter, $textParts); // insert the delimiter if supplied.
196
        if (!empty($text)) {
197
            return $this->wrapDisplayBlock($this->addAffixes($this->format(($text))));
198
        }
199
200
        return "";
201
    }
202
}
0 ignored issues
show
Coding Style introduced by
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
203