Completed
Push — authenticator-refactor ( fcc98b...4aec3f )
by Sam
05:51
created

testCollectFromCodeAdvanced()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 74
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 37
nc 1
nop 0
dl 0
loc 74
rs 9.0335
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SilverStripe\i18n\Tests;
4
5
use PHPUnit_Framework_Error_Notice;
6
use SilverStripe\Assets\Filesystem;
7
use SilverStripe\Core\Manifest\ModuleLoader;
8
use SilverStripe\Dev\SapphireTest;
9
use SilverStripe\i18n\i18n;
10
use SilverStripe\i18n\TextCollection\i18nTextCollector;
11
use SilverStripe\i18n\Messages\YamlWriter;
12
use SilverStripe\i18n\Tests\i18nTextCollectorTest\Collector;
13
14
class i18nTextCollectorTest extends SapphireTest
15
{
16
    use i18nTestManifest;
17
18
    /**
19
     * @var string
20
     */
21
    protected $alternateBaseSavePath = null;
22
23
    protected function setUp()
24
    {
25
        parent::setUp();
26
        $this->setupManifest();
27
28
        $this->alternateBaseSavePath = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'i18nTextCollectorTest_webroot';
29
        Filesystem::makeFolder($this->alternateBaseSavePath);
30
    }
31
32
    protected function tearDown()
33
    {
34
        if (is_dir($this->alternateBaseSavePath)) {
35
            Filesystem::removeFolder($this->alternateBaseSavePath);
36
        }
37
38
        $this->tearDownManifest();
39
        parent::tearDown();
40
    }
41
42 View Code Duplication
    public function testConcatenationInEntityValues()
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...
43
    {
44
        $c = i18nTextCollector::create();
45
        $module = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
46
47
        $php = <<<PHP
48
_t(
49
'Test.CONCATENATED',
50
'Line 1 and ' .
51
'Line \'2\' and ' .
52
'Line "3"',
53
54
'Comment'
55
);
56
57
_t(
58
'Test.CONCATENATED2',
59
"Line \"4\" and " .
60
"Line 5");
61
PHP;
62
        $this->assertEquals(
63
            array(
64
                'Test.CONCATENATED' => [
65
                    'default' => "Line 1 and Line '2' and Line \"3\"",
66
                    'comment' => 'Comment'
67
                ],
68
                'Test.CONCATENATED2' => "Line \"4\" and Line 5"
69
            ),
70
            $c->collectFromCode($php, null, $module)
0 ignored issues
show
Bug introduced by
It seems like $module defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 45 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
71
        );
72
    }
73
74
    public function testCollectFromNewTemplateSyntaxUsingParserSubclass()
75
    {
76
        $c = i18nTextCollector::create();
77
        $c->setWarnOnEmptyDefault(false);
78
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
79
80
        $html = <<<SS
81
        <% _t('Test.SINGLEQUOTE','Single Quote'); %>
82
<%t i18nTestModule.NEWMETHODSIG "New _t method signature test" %>
83
<%t i18nTestModule.INJECTIONS_0 "Hello {name} {greeting}, and {goodbye}" name="Mark" greeting="welcome" goodbye="bye" %>
84
<%t i18nTestModule.INJECTIONS_1 "Hello {name} {greeting}, and {goodbye}" name="Paul" greeting="welcome" goodbye="cya" %>
85
<%t i18nTestModule.INJECTIONS_2 "Hello {name} {greeting}" is "context (ignored)" name="Steffen" greeting="Wilkommen" %>
86
<%t i18nTestModule.INJECTIONS_3 name="Cat" greeting='meow' goodbye="meow" %>
87
<%t i18nTestModule.INJECTIONS_4 name=\$absoluteBaseURL greeting=\$get_locale goodbye="global calls" %>
88
<%t i18nTestModule.INJECTIONS_9 "An item|{count} items" is "Test Pluralisation" count=4 %>
89
<%t SilverStripe\\TestModule\\i18nTestModule.INJECTIONS_10 "This string is namespaced" %>
90
<%t SilverStripe\\\\TestModule\\\\i18nTestModule.INJECTIONS_11 "Escaped namespaced string" %>
91
SS;
92
        $c->collectFromTemplate($html, null, $mymodule);
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 78 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
93
94
        $this->assertEquals(
95
            [
96
                'Test.SINGLEQUOTE' => 'Single Quote',
97
                'i18nTestModule.NEWMETHODSIG' => "New _t method signature test",
98
                'i18nTestModule.INJECTIONS_0' => "Hello {name} {greeting}, and {goodbye}",
99
                'i18nTestModule.INJECTIONS_1' => "Hello {name} {greeting}, and {goodbye}",
100
                'i18nTestModule.INJECTIONS_2' => [
101
                    'default' => "Hello {name} {greeting}",
102
                    'comment' => 'context (ignored)',
103
                ],
104
                'i18nTestModule.INJECTIONS_9' => [
105
                    'one' => 'An item',
106
                    'other' => '{count} items',
107
                    'comment' => 'Test Pluralisation'
108
                ],
109
                'SilverStripe\\TestModule\\i18nTestModule.INJECTIONS_10' => 'This string is namespaced',
110
                'SilverStripe\\TestModule\\i18nTestModule.INJECTIONS_11' => 'Escaped namespaced string'
111
            ],
112
            $c->collectFromTemplate($html, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 78 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
113
        );
114
115
        // Test warning is raised on empty default
116
        $c->setWarnOnEmptyDefault(true);
117
        $this->setExpectedException(
118
            PHPUnit_Framework_Error_Notice::class,
119
            'Missing localisation default for key i18nTestModule.INJECTIONS_3'
120
        );
121
        $c->collectFromTemplate($html, null, $mymodule);
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 78 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
122
    }
123
124
    public function testCollectFromTemplateSimple()
125
    {
126
        $c = i18nTextCollector::create();
127
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
128
129
        $html = <<<SS
130
<% _t('Test.SINGLEQUOTE','Single Quote'); %>
131
SS;
132
        $this->assertEquals(
133
            [ 'Test.SINGLEQUOTE' => 'Single Quote' ],
134
            $c->collectFromTemplate($html, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 127 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
135
        );
136
137
        $html = <<<SS
138
<% _t(  "Test.DOUBLEQUOTE", "Double Quote and Spaces"   ); %>
139
SS;
140
        $this->assertEquals(
141
            [ 'Test.DOUBLEQUOTE' => "Double Quote and Spaces" ],
142
            $c->collectFromTemplate($html, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 127 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
143
        );
144
145
        $html = <<<SS
146
<% _t("Test.NOSEMICOLON","No Semicolon") %>
147
SS;
148
        $this->assertEquals(
149
            [ 'Test.NOSEMICOLON' => "No Semicolon" ],
150
            $c->collectFromTemplate($html, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 127 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
151
        );
152
    }
153
154
    public function testCollectFromTemplateAdvanced()
155
    {
156
        $c = i18nTextCollector::create();
157
        $c->setWarnOnEmptyDefault(false);
158
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
159
160
        $html = <<<SS
161
<% _t(
162
	'NEWLINES',
163
	'New Lines'
164
) %>
165
SS;
166
        $this->assertEquals(
167
            [ 'Test.NEWLINES' => "New Lines" ],
168
            $c->collectFromTemplate($html, 'Test', $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 158 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
169
        );
170
171
        $html = <<<SS
172
<% _t(
173
	'Test.PRIOANDCOMMENT',
174
	' Prio and Value with "Double Quotes"',
175
	'Comment with "Double Quotes"'
176
) %>
177
SS;
178
        $this->assertEquals(
179
            [ 'Test.PRIOANDCOMMENT' => [
180
                'default' => ' Prio and Value with "Double Quotes"',
181
                'comment' => 'Comment with "Double Quotes"',
182
            ]],
183
            $c->collectFromTemplate($html, 'Test', $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 158 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
184
        );
185
186
        $html = <<<SS
187
<% _t(
188
	'Test.PRIOANDCOMMENT',
189
	" Prio and Value with 'Single Quotes'",
190
191
	"Comment with 'Single Quotes'"
192
) %>
193
SS;
194
        $this->assertEquals(
195
            [ 'Test.PRIOANDCOMMENT' => [
196
                'default' => " Prio and Value with 'Single Quotes'",
197
                'comment' => "Comment with 'Single Quotes'",
198
            ]],
199
            $c->collectFromTemplate($html, 'Test', $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 158 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
200
        );
201
202
        // Test empty
203
        $html = <<<SS
204
<% _t('Test.PRIOANDCOMMENT') %>
205
SS;
206
        $this->assertEquals(
207
            [],
208
            $c->collectFromTemplate($html, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 158 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
209
        );
210
211
        // Test warning is raised on empty default
212
        $c->setWarnOnEmptyDefault(true);
213
        $this->setExpectedException(
214
            PHPUnit_Framework_Error_Notice::class,
215
            'Missing localisation default for key Test.PRIOANDCOMMENT'
216
        );
217
        $c->collectFromTemplate($html, 'Test', $mymodule);
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 158 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
218
    }
219
220
221
    public function testCollectFromCodeSimple()
222
    {
223
        $c = i18nTextCollector::create();
224
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
225
226
        $php = <<<PHP
227
_t('Test.SINGLEQUOTE','Single Quote');
228
PHP;
229
        $this->assertEquals(
230
            [ 'Test.SINGLEQUOTE' => 'Single Quote' ],
231
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 224 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
232
        );
233
234
        $php = <<<PHP
235
_t(  "Test.DOUBLEQUOTE", "Double Quote and Spaces"   );
236
PHP;
237
        $this->assertEquals(
238
            [ 'Test.DOUBLEQUOTE' => "Double Quote and Spaces" ],
239
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 224 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
240
        );
241
    }
242
243
    public function testCollectFromCodeAdvanced()
244
    {
245
        $c = i18nTextCollector::create();
246
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
247
248
        $php = <<<PHP
249
_t(
250
	'Test.NEWLINES',
251
	'New Lines'
252
);
253
PHP;
254
        $this->assertEquals(
255
            [ 'Test.NEWLINES' => "New Lines" ],
256
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 246 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
257
        );
258
259
        $php = <<<PHP
260
_t(
261
	'Test.PRIOANDCOMMENT',
262
	' Value with "Double Quotes"',
263
264
	'Comment with "Double Quotes"'
265
);
266
PHP;
267
        $this->assertEquals(
268
            [
269
                'Test.PRIOANDCOMMENT' => [
270
                    'default' => ' Value with "Double Quotes"',
271
                    'comment' => 'Comment with "Double Quotes"',
272
                ]
273
            ],
274
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 246 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
275
        );
276
277
        $php = <<<PHP
278
_t(
279
	'Test.PRIOANDCOMMENT',
280
	" Value with 'Single Quotes'",
281
282
	"Comment with 'Single Quotes'"
283
);
284
PHP;
285
        $this->assertEquals(
286
            [ 'Test.PRIOANDCOMMENT' => [
287
                'default' => " Value with 'Single Quotes'",
288
                'comment' => "Comment with 'Single Quotes'"
289
            ] ],
290
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 246 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
291
        );
292
293
        $php = <<<PHP
294
_t(
295
	'Test.PRIOANDCOMMENT',
296
	'Value with \'Escaped Single Quotes\''
297
);
298
PHP;
299
        $this->assertEquals(
300
            [ 'Test.PRIOANDCOMMENT' => "Value with 'Escaped Single Quotes'" ],
301
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 246 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
302
        );
303
304
        $php = <<<PHP
305
_t(
306
	'Test.PRIOANDCOMMENT',
307
	"Doublequoted Value with 'Unescaped Single Quotes'"
308
	
309
	
310
);
311
PHP;
312
        $this->assertEquals(
313
            [ 'Test.PRIOANDCOMMENT' => "Doublequoted Value with 'Unescaped Single Quotes'"],
314
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 246 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
315
        );
316
    }
317
318 View Code Duplication
    public function testCollectFromCodeNamespace()
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...
319
    {
320
        $c = i18nTextCollector::create();
321
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
322
        $php = <<<PHP
323
<?php
324
namespace SilverStripe\Framework\Core;
325
326
class MyClass extends Base implements SomeService {
327
    public function getNewLines() {
328
        return _t(
329
            __CLASS__.'.NEWLINES',
330
            'New Lines'
331
        );
332
    }
333
    public function getAnotherString() {
334
        return _t(
335
            'SilverStripe\\\\Framework\\\\MyClass.ANOTHER_STRING',
336
            'Slash=\\\\, Quote=\\''
337
        );
338
    }
339
    public function getDoubleQuotedString() {
340
        return _t(
341
            "SilverStripe\\\\Framework\\\\MyClass.DOUBLE_STRING",
342
            "Slash=\\\\, Quote=\\""
343
        );
344
    }
345
}
346
PHP;
347
        $this->assertEquals(
348
            [
349
                'SilverStripe\\Framework\\Core\\MyClass.NEWLINES' => "New Lines",
350
                'SilverStripe\\Framework\\MyClass.ANOTHER_STRING' => 'Slash=\\, Quote=\'',
351
                'SilverStripe\\Framework\\MyClass.DOUBLE_STRING' => 'Slash=\\, Quote="'
352
            ],
353
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 321 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
354
        );
355
    }
356
357
358
    public function testNewlinesInEntityValues()
359
    {
360
        $c = i18nTextCollector::create();
361
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
362
363
        $php = <<<PHP
364
_t(
365
'Test.NEWLINESINGLEQUOTE',
366
'Line 1
367
Line 2'
368
);
369
PHP;
370
371
        $eol = PHP_EOL;
372
        $this->assertEquals(
373
            [ 'Test.NEWLINESINGLEQUOTE' => "Line 1{$eol}Line 2" ],
374
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 361 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
375
        );
376
377
        $php = <<<PHP
378
_t(
379
'Test.NEWLINEDOUBLEQUOTE',
380
"Line 1
381
Line 2"
382
);
383
PHP;
384
        $this->assertEquals(
385
            [ 'Test.NEWLINEDOUBLEQUOTE' => "Line 1{$eol}Line 2" ],
386
            $c->collectFromCode($php, null, $mymodule)
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 361 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
387
        );
388
    }
389
390
    /**
391
     * Test extracting entities from the new _t method signature
392
     */
393
    public function testCollectFromCodeNewSignature()
394
    {
395
        $c = i18nTextCollector::create();
396
        $c->setWarnOnEmptyDefault(false); // Disable warnings for tests
397
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
398
399
        $php = <<<PHP
400
_t('i18nTestModule.NEWMETHODSIG',"New _t method signature test");
401
_t('i18nTestModule.INJECTIONS2', "Hello {name} {greeting}. But it is late, {goodbye}",
402
	array("name"=>"Paul", "greeting"=>"good you are here", "goodbye"=>"see you"));
403
_t("i18nTestModule.INJECTIONS3", "Hello {name} {greeting}. But it is late, {goodbye}",
404
		"New context (this should be ignored)",
405
		array("name"=>"Steffen", "greeting"=>"willkommen", "goodbye"=>"wiedersehen"));
406
_t('i18nTestModule.INJECTIONS4', array("name"=>"Cat", "greeting"=>"meow", "goodbye"=>"meow"));
407
_t('i18nTestModule.INJECTIONS6', "Hello {name} {greeting}. But it is late, {goodbye}",
408
	["name"=>"Paul", "greeting"=>"good you are here", "goodbye"=>"see you"]);
409
_t("i18nTestModule.INJECTIONS7", "Hello {name} {greeting}. But it is late, {goodbye}",
410
		"New context (this should be ignored)",
411
		["name"=>"Steffen", "greeting"=>"willkommen", "goodbye"=>"wiedersehen"]);
412
_t('i18nTestModule.INJECTIONS8', ["name"=>"Cat", "greeting"=>"meow", "goodbye"=>"meow"]);
413
_t('i18nTestModule.INJECTIONS9', "An item|{count} items", ['count' => 4], "Test Pluralisation");
414
PHP;
415
416
        $collectedTranslatables = $c->collectFromCode($php, null, $mymodule);
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 397 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
417
418
        $expectedArray = [
419
            'i18nTestModule.INJECTIONS2' => "Hello {name} {greeting}. But it is late, {goodbye}",
420
            'i18nTestModule.INJECTIONS3' => [
421
                'default' => "Hello {name} {greeting}. But it is late, {goodbye}",
422
                'comment' => 'New context (this should be ignored)'
423
            ],
424
            'i18nTestModule.INJECTIONS6' => "Hello {name} {greeting}. But it is late, {goodbye}",
425
            'i18nTestModule.INJECTIONS7' => [
426
                'default' => "Hello {name} {greeting}. But it is late, {goodbye}",
427
                'comment' => "New context (this should be ignored)",
428
            ],
429
            'i18nTestModule.INJECTIONS9' => [
430
                'one' => 'An item',
431
                'other' => '{count} items',
432
                'comment' => 'Test Pluralisation',
433
            ],
434
            'i18nTestModule.NEWMETHODSIG' => "New _t method signature test",
435
        ];
436
        $this->assertEquals($expectedArray, $collectedTranslatables);
437
438
        // Test warning is raised on empty default
439
        $this->setExpectedException(
440
            PHPUnit_Framework_Error_Notice::class,
441
            'Missing localisation default for key i18nTestModule.INJECTIONS4'
442
        );
443
        $php = <<<PHP
444
_t('i18nTestModule.INJECTIONS4', array("name"=>"Cat", "greeting"=>"meow", "goodbye"=>"meow"));
445
PHP;
446
        $c->setWarnOnEmptyDefault(true);
447
        $c->collectFromCode($php, null, $mymodule);
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 397 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
448
    }
449
450
    public function testUncollectableCode()
451
    {
452
        $c = i18nTextCollector::create();
453
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
454
455
        $php = <<<PHP
456
_t(static::class.'.KEY1', 'Default');
457
_t(self::class.'.KEY2', 'Default');
458
_t(__CLASS__.'.KEY3', 'Default');
459
_t('Collectable.KEY4', 'Default');
460
PHP;
461
462
        $collectedTranslatables = $c->collectFromCode($php, null, $mymodule);
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 453 can be null; however, SilverStripe\i18n\TextCo...ctor::collectFromCode() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
463
464
        // Only one item is collectable
465
        $expectedArray = [ 'Collectable.KEY4' => 'Default' ];
466
        $this->assertEquals($expectedArray, $collectedTranslatables);
467
    }
468
469
    public function testCollectFromIncludedTemplates()
470
    {
471
        $c = i18nTextCollector::create();
472
        $c->setWarnOnEmptyDefault(false); // Disable warnings for tests
473
        $mymodule = ModuleLoader::instance()->getManifest()->getModule('i18ntestmodule');
474
475
        $templateFilePath = $this->alternateBasePath . '/i18ntestmodule/templates/Layout/i18nTestModule.ss';
476
        $html = file_get_contents($templateFilePath);
477
        $matches = $c->collectFromTemplate($html, $templateFilePath, $mymodule);
0 ignored issues
show
Bug introduced by
It seems like $mymodule defined by \SilverStripe\Core\Manif...odule('i18ntestmodule') on line 473 can be null; however, SilverStripe\i18n\TextCo...::collectFromTemplate() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
478
479
        $this->assertArrayHasKey('i18nTestModule.ss.LAYOUTTEMPLATENONAMESPACE', $matches);
480
        $this->assertEquals(
481
            'Layout Template no namespace',
482
            $matches['i18nTestModule.ss.LAYOUTTEMPLATENONAMESPACE']
483
        );
484
        $this->assertArrayHasKey('i18nTestModule.ss.SPRINTFNONAMESPACE', $matches);
485
        $this->assertEquals(
486
            'My replacement no namespace: %s',
487
            $matches['i18nTestModule.ss.SPRINTFNONAMESPACE']
488
        );
489
        $this->assertArrayHasKey('i18nTestModule.LAYOUTTEMPLATE', $matches);
490
        $this->assertEquals(
491
            'Layout Template',
492
            $matches['i18nTestModule.LAYOUTTEMPLATE']
493
        );
494
        $this->assertArrayHasKey('i18nTestModule.SPRINTFNAMESPACE', $matches);
495
        $this->assertEquals(
496
            'My replacement: %s',
497
            $matches['i18nTestModule.SPRINTFNAMESPACE']
498
        );
499
500
        // Includes should not automatically inject translations into parent templates
501
        $this->assertArrayNotHasKey('i18nTestModule.WITHNAMESPACE', $matches);
502
        $this->assertArrayNotHasKey('i18nTestModuleInclude.ss.NONAMESPACE', $matches);
503
        $this->assertArrayNotHasKey('i18nTestModuleInclude.ss.SPRINTFINCLUDENAMESPACE', $matches);
504
        $this->assertArrayNotHasKey('i18nTestModuleInclude.ss.SPRINTFINCLUDENONAMESPACE', $matches);
505
    }
506
507
    public function testCollectMergesWithExisting()
508
    {
509
        $c = i18nTextCollector::create();
510
        $c->setWarnOnEmptyDefault(false);
511
        $c->setWriter(new YamlWriter());
512
        $c->basePath = $this->alternateBasePath;
513
        $c->baseSavePath = $this->alternateBaseSavePath;
514
515
        $entitiesByModule = $c->collect(null, true /* merge */);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
516
        $this->assertArrayHasKey(
517
            'i18nTestModule.ENTITY',
518
            $entitiesByModule['i18ntestmodule'],
519
            'Retains existing entities'
520
        );
521
        $this->assertArrayHasKey(
522
            'i18nTestModule.NEWENTITY',
523
            $entitiesByModule['i18ntestmodule'],
524
            'Adds new entities'
525
        );
526
527
        // Test cross-module strings are set correctly
528
        $this->assertArrayHasKey(
529
            'i18nProviderClass.OTHER_MODULE',
530
            $entitiesByModule['i18ntestmodule']
531
        );
532
        $this->assertEquals(
533
            [
534
                'comment' => 'Test string in another module',
535
                'default' => 'i18ntestmodule string defined in i18nothermodule',
536
            ],
537
            $entitiesByModule['i18ntestmodule']['i18nProviderClass.OTHER_MODULE']
538
        );
539
    }
540
541
    public function testCollectFromFilesystemAndWriteMasterTables()
542
    {
543
        i18n::set_locale('en_US');  //set the locale to the US locale expected in the asserts
544
        i18n::config()->update('default_locale', 'en_US');
545
        i18n::config()->update('missing_default_warning', false);
546
547
        $c = i18nTextCollector::create();
548
        $c->setWarnOnEmptyDefault(false);
549
        $c->setWriter(new YamlWriter());
550
        $c->basePath = $this->alternateBasePath;
551
        $c->baseSavePath = $this->alternateBaseSavePath;
552
553
        $c->run();
554
555
        // i18ntestmodule
556
        $moduleLangFile = "{$this->alternateBaseSavePath}/i18ntestmodule/lang/" . $c->getDefaultLocale() . '.yml';
557
        $this->assertTrue(
558
            file_exists($moduleLangFile),
559
            'Master language file can be written to modules /lang folder'
560
        );
561
562
        $moduleLangFileContent = file_get_contents($moduleLangFile);
563
        $this->assertContains(
564
            "    ADDITION: Addition\n",
565
            $moduleLangFileContent
566
        );
567
        $this->assertContains(
568
            "    ENTITY: 'Entity with \"Double Quotes\"'\n",
569
            $moduleLangFileContent
570
        );
571
        $this->assertContains(
572
            "    MAINTEMPLATE: 'Main Template'\n",
573
            $moduleLangFileContent
574
        );
575
        $this->assertContains(
576
            "    OTHERENTITY: 'Other Entity'\n",
577
            $moduleLangFileContent
578
        );
579
        $this->assertContains(
580
            "    WITHNAMESPACE: 'Include Entity with Namespace'\n",
581
            $moduleLangFileContent
582
        );
583
        $this->assertContains(
584
            "    NONAMESPACE: 'Include Entity without Namespace'\n",
585
            $moduleLangFileContent
586
        );
587
588
        // i18nothermodule
589
        $otherModuleLangFile = "{$this->alternateBaseSavePath}/i18nothermodule/lang/" . $c->getDefaultLocale() . '.yml';
590
        $this->assertTrue(
591
            file_exists($otherModuleLangFile),
592
            'Master language file can be written to modules /lang folder'
593
        );
594
        $otherModuleLangFileContent = file_get_contents($otherModuleLangFile);
595
        $this->assertContains(
596
            "    ENTITY: 'Other Module Entity'\n",
597
            $otherModuleLangFileContent
598
        );
599
        $this->assertContains(
600
            "    MAINTEMPLATE: 'Main Template Other Module'\n",
601
            $otherModuleLangFileContent
602
        );
603
    }
604
605
    public function testCollectFromEntityProvidersInCustomObject()
606
    {
607
        // note: Disable _fakewebroot manifest for this test
608
        $this->popManifests();
609
610
        $c = i18nTextCollector::create();
611
612
        // Collect from MyObject.php
613
        $filePath = __DIR__ . '/i18nTest/MyObject.php';
614
        $matches = $c->collectFromEntityProviders($filePath);
615
        $this->assertEquals(
616
            [
617
                'SilverStripe\Admin\LeftAndMain.OTHER_TITLE' => [
618
                    'default' => 'Other title',
619
                    'module' => 'admin',
620
                ],
621
                'SilverStripe\i18n\Tests\i18nTest\MyObject.PLURALNAME' => 'My Objects',
622
                'SilverStripe\i18n\Tests\i18nTest\MyObject.PLURALS' => [
623
                    'one' => 'A My Object',
624
                    'other' => '{count} My Objects',
625
                ],
626
                'SilverStripe\i18n\Tests\i18nTest\MyObject.SINGULARNAME' => 'My Object',
627
            ],
628
            $matches
629
        );
630
    }
631
632
    public function testCollectFromEntityProvidersInWebRoot()
633
    {
634
        // Collect from i18nProviderClass
635
        $c = i18nTextCollector::create();
636
        $c->setWarnOnEmptyDefault(false);
637
        $c->setWriter(new YamlWriter());
638
        $c->basePath = $this->alternateBasePath;
639
        $c->baseSavePath = $this->alternateBaseSavePath;
640
        $entitiesByModule = $c->collect(null, false);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
641
        $this->assertEquals(
642
            [
643
                'comment' => 'Plural forms for the test class',
644
                'one' => 'A class',
645
                'other' => '{count} classes',
646
            ],
647
            $entitiesByModule['i18nothermodule']['i18nProviderClass.PLURALS']
648
        );
649
        $this->assertEquals(
650
            'My Provider Class',
651
            $entitiesByModule['i18nothermodule']['i18nProviderClass.TITLE']
652
        );
653
        $this->assertEquals(
654
            [
655
                'comment' => 'Test string in another module',
656
                'default' => 'i18ntestmodule string defined in i18nothermodule',
657
            ],
658
            $entitiesByModule['i18ntestmodule']['i18nProviderClass.OTHER_MODULE']
659
        );
660
    }
661
662
    /**
663
     * Test that duplicate keys are resolved to the appropriate modules
664
     */
665
    public function testResolveDuplicates()
666
    {
667
        $collector = new Collector();
668
669
        // Dummy data as collected
670
        $data1 = [
671
            'i18ntestmodule' => [
672
                'i18nTestModule.PLURALNAME' => 'Data Objects',
673
                'i18nTestModule.SINGULARNAME' => 'Data Object',
674
            ],
675
            'mymodule' => [
676
                'i18nTestModule.PLURALNAME' => 'Ignored String',
677
                'i18nTestModule.STREETNAME' => 'Shortland Street',
678
            ],
679
        ];
680
        $expected = [
681
            'i18ntestmodule' => [
682
                'i18nTestModule.PLURALNAME' => 'Data Objects',
683
                'i18nTestModule.SINGULARNAME' => 'Data Object',
684
            ],
685
            'mymodule' => [
686
                // Removed PLURALNAME because this key doesn't exist in i18ntestmodule strings
687
                'i18nTestModule.STREETNAME' => 'Shortland Street'
688
            ]
689
        ];
690
691
        $resolved = $collector->resolveDuplicateConflicts_Test($data1);
692
        $this->assertEquals($expected, $resolved);
693
694
        // Test getConflicts
695
        $data2 = [
696
            'module1' => [
697
                'i18ntestmodule.ONE' => 'One',
698
                'i18ntestmodule.TWO' => 'Two',
699
                'i18ntestmodule.THREE' => 'Three',
700
            ],
701
            'module2' => [
702
                'i18ntestmodule.THREE' => 'Three',
703
            ],
704
            'module3' => [
705
                'i18ntestmodule.TWO' => 'Two',
706
                'i18ntestmodule.THREE' => 'Three',
707
            ],
708
        ];
709
        $conflictsA = $collector->getConflicts_Test($data2);
710
        sort($conflictsA);
711
        $this->assertEquals(
712
            array('i18ntestmodule.THREE', 'i18ntestmodule.TWO'),
713
            $conflictsA
714
        );
715
716
        // Removing module3 should remove a conflict
717
        unset($data2['module3']);
718
        $conflictsB = $collector->getConflicts_Test($data2);
719
        $this->assertEquals(
720
            array('i18ntestmodule.THREE'),
721
            $conflictsB
722
        );
723
    }
724
725
    /**
726
     * Test ability for textcollector to detect modules
727
     */
728
    public function testModuleDetection()
729
    {
730
        $collector = new Collector();
731
        $modules = ModuleLoader::instance()->getManifest()->getModules();
732
        $this->assertEquals(
733
            array(
734
                'i18nnonstandardmodule',
735
                'i18ntestmodule',
736
                'i18nothermodule'
737
            ),
738
            array_keys($modules)
739
        );
740
741
        $this->assertEquals('i18ntestmodule', $collector->findModuleForClass_Test('i18nTestNamespacedClass'));
742
        $this->assertEquals(
743
            'i18ntestmodule',
744
            $collector->findModuleForClass_Test('i18nTest\\i18nTestNamespacedClass')
745
        );
746
        $this->assertEquals('i18ntestmodule', $collector->findModuleForClass_Test('i18nTestSubModule'));
747
    }
748
749
    /**
750
     * Test that text collector can detect module file lists properly
751
     */
752
    public function testModuleFileList()
753
    {
754
        $collector = new Collector();
755
        $collector->basePath = $this->alternateBasePath;
756
        $collector->baseSavePath = $this->alternateBaseSavePath;
757
758
        // Non-standard modules can't be safely filtered, so just index everything
759
        $nonStandardFiles = $collector->getFileListForModule_Test('i18nnonstandardmodule');
760
        $nonStandardRoot = $this->alternateBasePath . '/i18nnonstandardmodule';
761
        $this->assertEquals(3, count($nonStandardFiles));
762
        $this->assertArrayHasKey("{$nonStandardRoot}/_config.php", $nonStandardFiles);
763
        $this->assertArrayHasKey("{$nonStandardRoot}/phpfile.php", $nonStandardFiles);
764
        $this->assertArrayHasKey("{$nonStandardRoot}/template.ss", $nonStandardFiles);
765
766
        // Normal module should have predictable dir structure
767
        $testFiles = $collector->getFileListForModule_Test('i18ntestmodule');
768
        $testRoot = $this->alternateBasePath . '/i18ntestmodule';
769
        $this->assertEquals(7, count($testFiles));
770
        // Code in code folder is detected
771
        $this->assertArrayHasKey("{$testRoot}/code/i18nTestModule.php", $testFiles);
772
        $this->assertArrayHasKey("{$testRoot}/code/subfolder/_config.php", $testFiles);
773
        $this->assertArrayHasKey("{$testRoot}/code/subfolder/i18nTestSubModule.php", $testFiles);
774
        $this->assertArrayHasKey("{$testRoot}/code/subfolder/i18nTestNamespacedClass.php", $testFiles);
775
        // Templates in templates folder is detected
776
        $this->assertArrayHasKey("{$testRoot}/templates/Includes/i18nTestModuleInclude.ss", $testFiles);
777
        $this->assertArrayHasKey("{$testRoot}/templates/Layout/i18nTestModule.ss", $testFiles);
778
        $this->assertArrayHasKey("{$testRoot}/templates/i18nTestModule.ss", $testFiles);
779
780
        // Standard modules with code in odd places should only have code in those directories detected
781
        $otherFiles = $collector->getFileListForModule_Test('i18nothermodule');
782
        $otherRoot = $this->alternateBasePath . '/i18nothermodule';
783
        $this->assertEquals(4, count($otherFiles));
784
        // Only detect well-behaved files
785
        $this->assertArrayHasKey("{$otherRoot}/code/i18nOtherModule.php", $otherFiles);
786
        $this->assertArrayHasKey("{$otherRoot}/code/i18nProviderClass.php", $otherFiles);
787
        $this->assertArrayHasKey("{$otherRoot}/code/i18nTestModuleDecorator.php", $otherFiles);
788
        $this->assertArrayHasKey("{$otherRoot}/templates/i18nOtherModule.ss", $otherFiles);
789
    }
790
}
791