Skip to content

Commit eddcbe9

Browse files
xurizaemonAnt Brown
and
Ant Brown
authored
Prevent warnings when $parsed_date[EDTFUtils::YEAR_BASE] is not set (#139)
* #139: Add tests for inputs which trigger warnings * #139: Check YEAR_BASE key exists before using --------- Co-authored-by: Ant Brown <[email protected]>
1 parent 05a0811 commit eddcbe9

File tree

2 files changed

+253
-17
lines changed

2 files changed

+253
-17
lines changed

src/Plugin/Field/FieldFormatter/EDTFFormatter.php

+19-17
Original file line numberDiff line numberDiff line change
@@ -241,24 +241,26 @@ protected function formatDate($edtf_text) {
241241
];
242242
$unspecified_count = 0;
243243

244-
if (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'XXXX') !== FALSE) {
245-
$unspecified['fullyear'] = TRUE;
246-
$unspecified_count++;
247-
}
248-
elseif (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'XXX') !== FALSE) {
249-
$unspecified['century'] = TRUE;
250-
$unspecified_count++;
251-
}
252-
elseif (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'XX') !== FALSE) {
253-
$unspecified['decade'] = TRUE;
254-
$unspecified_count++;
255-
}
256-
elseif (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'X') !== FALSE) {
257-
$unspecified['year'] = TRUE;
258-
$unspecified_count++;
259-
}
244+
if (array_key_exists(EDTFUtils::YEAR_BASE, $parsed_date)) {
245+
if (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'XXXX') !== FALSE) {
246+
$unspecified['fullyear'] = TRUE;
247+
$unspecified_count++;
248+
}
249+
elseif (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'XXX') !== FALSE) {
250+
$unspecified['century'] = TRUE;
251+
$unspecified_count++;
252+
}
253+
elseif (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'XX') !== FALSE) {
254+
$unspecified['decade'] = TRUE;
255+
$unspecified_count++;
256+
}
257+
elseif (strpos($parsed_date[EDTFUtils::YEAR_BASE], 'X') !== FALSE) {
258+
$unspecified['year'] = TRUE;
259+
$unspecified_count++;
260+
}
260261

261-
$year = $parsed_date[EDTFUtils::YEAR_BASE];
262+
$year = $parsed_date[EDTFUtils::YEAR_BASE];
263+
}
262264

263265
if (array_key_exists(EDTFUtils::MONTH, $parsed_date)) {
264266
if (strpos($parsed_date[EDTFUtils::MONTH], 'X') !== FALSE) {
+234
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
<?php
2+
3+
namespace Drupal\Tests\controlled_access_terms\Kernel\Plugin\Field\FieldFormatter;
4+
5+
use Drupal\KernelTests\KernelTestBase;
6+
use Drupal\field\Entity\FieldConfig;
7+
use Drupal\field\Entity\FieldStorageConfig;
8+
use Drupal\node\Entity\NodeType;
9+
use Drupal\node\Entity\Node;
10+
use Drupal\Core\Field\FieldStorageDefinitionInterface;
11+
12+
/**
13+
* Tests the EDTFFormatter field formatter.
14+
*
15+
* @group controlled_access_terms
16+
*/
17+
class EDTFFormatterTest extends KernelTestBase {
18+
19+
/**
20+
* {@inheritdoc}
21+
*/
22+
protected static $modules = [
23+
'system',
24+
'node',
25+
'field',
26+
'text',
27+
'user',
28+
'controlled_access_terms',
29+
];
30+
31+
/**
32+
* The node type for testing.
33+
*
34+
* @var \Drupal\node\Entity\NodeType
35+
*/
36+
protected $nodeType;
37+
38+
/**
39+
* The field storage configuration for the test field.
40+
*
41+
* @var \Drupal\field\Entity\FieldStorageConfig
42+
*/
43+
protected $fieldStorage;
44+
45+
/**
46+
* The field configuration for the test field.
47+
*
48+
* @var \Drupal\field\Entity\FieldConfig
49+
*/
50+
protected $field;
51+
52+
/**
53+
* The formatter being tested.
54+
*
55+
* @var \Drupal\controlled_access_terms\Plugin\Field\FieldFormatter\EDTFFormatter
56+
*/
57+
protected $formatter;
58+
59+
/**
60+
* {@inheritdoc}
61+
*/
62+
protected function setUp(): void {
63+
parent::setUp();
64+
65+
// Install necessary schemas.
66+
$this->installEntitySchema('node');
67+
$this->installEntitySchema('user');
68+
$this->installEntitySchema('field_storage_config');
69+
$this->installEntitySchema('field_config');
70+
$this->installSchema('node', ['node_access']);
71+
72+
// Create a content type.
73+
$this->nodeType = NodeType::create([
74+
'type' => 'test_content',
75+
'name' => 'Test Content',
76+
]);
77+
$this->nodeType->save();
78+
79+
// Create EDTF field storage.
80+
$this->fieldStorage = FieldStorageConfig::create([
81+
'field_name' => 'field_edtf',
82+
'entity_type' => 'node',
83+
'type' => 'edtf',
84+
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
85+
]);
86+
$this->fieldStorage->save();
87+
88+
// Attach field to content type.
89+
$this->field = FieldConfig::create([
90+
'field_storage' => $this->fieldStorage,
91+
'bundle' => $this->nodeType->id(),
92+
'label' => 'EDTF Field',
93+
]);
94+
$this->field->save();
95+
96+
// Configure display.
97+
\Drupal::service('entity_display.repository')->getViewDisplay('node', $this->nodeType->id(), 'default')
98+
->setComponent('field_edtf', [
99+
'type' => 'edtf_default',
100+
])
101+
->save();
102+
}
103+
104+
/**
105+
* Test formatter output returns a render array with various EDTF dates.
106+
*/
107+
public function testFormatterOutput() {
108+
$node = Node::create([
109+
'type' => $this->nodeType->id(),
110+
'title' => 'Test EDTF Node',
111+
'field_edtf' => [
112+
// Single date.
113+
['value' => '2023-10-15'],
114+
// Year interval.
115+
['value' => '2023/2024'],
116+
// Date interval.
117+
['value' => '2022-06-01/2023-12-31'],
118+
],
119+
]);
120+
$node->save();
121+
122+
$build = $node->get('field_edtf')->view();
123+
$this->assertNotEmpty($build, 'Render array is not empty');
124+
}
125+
126+
/**
127+
* Test EDTFFormatter date formatting method.
128+
*
129+
* @dataProvider edtfDateFormatProvider
130+
*/
131+
public function testDateFormatting(string $input, string $expected) : void {
132+
// Create the formatter.
133+
$formatter = $this->container->get('plugin.manager.field.formatter')
134+
->createInstance('edtf_default', [
135+
'field_definition' => $this->field,
136+
'settings' => [],
137+
'label' => '',
138+
'view_mode' => 'default',
139+
'third_party_settings' => [],
140+
]);
141+
142+
// Use reflection to access the protected formatDate method.
143+
$reflectionMethod = new \ReflectionMethod($formatter, 'formatDate');
144+
$reflectionMethod->setAccessible(TRUE);
145+
146+
// Perform the formatting.
147+
$result = $reflectionMethod->invoke($formatter, $input);
148+
149+
// Assert the result.
150+
$this->assertEquals($expected, $result,
151+
"Failed formatting for input: $input. Expected: $expected, Got: $result");
152+
}
153+
154+
/**
155+
* Data provider for EDTF date formatting tests.
156+
*
157+
* @return array
158+
* Array of test inputs.
159+
*/
160+
public function edtfDateFormatProvider(): array {
161+
return [
162+
// EDTF Level 0.
163+
'Date - complete' => [
164+
'input' => '1985-04-12',
165+
'expected' => '1985-04-12',
166+
],
167+
'Date - reduced precision - year and month' => [
168+
'input' => '1985-04',
169+
'expected' => '1985-04',
170+
],
171+
'Date - reduced precision - year' => [
172+
'input' => '1985',
173+
'expected' => '1985',
174+
],
175+
'Date and time - local' => [
176+
'original' => '2024-10-15T12:00:00',
177+
'formatted' => '2024-10-15 12:00:00',
178+
],
179+
'Date and time - Z' => [
180+
'original' => '1985-04-12T23:20:30Z',
181+
'formatted' => '1985-04-12 23:20:30Z',
182+
],
183+
'Date and time - shift in hours' => [
184+
'original' => '1985-04-12T23:20:30+04',
185+
'formatted' => '1985-04-12 23:20:30+04',
186+
],
187+
'Date and time - shift in hours and minutes' => [
188+
'original' => '1985-04-12T23:20:30+04:30',
189+
'formatted' => '1985-04-12 23:20:30+04:30',
190+
],
191+
192+
// EDTF level 1.
193+
'Uncertain year' => [
194+
'input' => '1984?',
195+
'expected' => '1984 (year uncertain)',
196+
],
197+
'Uncertain year and month' => [
198+
'original' => '2024-10%',
199+
'formatted' => '2024-10 (year and month uncertain; year and month approximate)',
200+
],
201+
'Approximate year' => [
202+
'input' => '1984~',
203+
'expected' => '1984 (year approximate)',
204+
],
205+
'Approximate year and month' => [
206+
'original' => '2024-10~',
207+
'formatted' => '2024-10 (year and month approximate)',
208+
],
209+
'Year and month' => [
210+
'original' => '2024-10',
211+
'formatted' => '2024-10',
212+
],
213+
'Unspecified digits from right' => [
214+
'input' => '198X',
215+
'expected' => 'Unknown year in the decade of the 1980s',
216+
],
217+
218+
// Invalid/edge cases.
219+
'Empty input' => [
220+
'input' => '',
221+
'expected' => '',
222+
],
223+
'Invalid date format' => [
224+
'input' => 'invalid-date',
225+
'expected' => '',
226+
],
227+
'Invalid (date-like)' => [
228+
'original' => '1900s',
229+
'formatted' => '',
230+
],
231+
];
232+
}
233+
234+
}

0 commit comments

Comments
 (0)