Completed
Branch 2.5/TaskLists (638e96)
by Josh
03:37
created

Helper::setTaskState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 15
ccs 9
cts 9
cp 1
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 4
crap 1
1
<?php declare(strict_types=1);
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2020 The s9e authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Plugins\TaskLists;
9
10
use s9e\TextFormatter\Parser;
11
use s9e\TextFormatter\Parser\Tag;
12
13
class Helper
14
{
15 5
	public static function filterListItem(Parser $parser, Tag $listItem, string $text): void
16
	{
17
		// Test whether the list item is followed by a task checkbox
18 5
		$pos  = $listItem->getPos() + $listItem->getLen();
19 5
		$pos += strspn($text, ' ', $pos);
20 5
		$str  = substr($text, $pos, 3);
21 5
		if (!preg_match('/\\[[ Xx]\\]/', $str))
22
		{
23
			return;
24
		}
25
26
		// Create a tag for the task and assign it a random ID
27 5
		$taskId    = uniqid();
28 5
		$taskState = ($str === '[ ]') ? 'incomplete' : 'complete';
29
30 5
		$task = $parser->addSelfClosingTag('TASK', $pos, 3);
31 5
		$task->setAttribute('id',    $taskId);
32 5
		$task->setAttribute('state', $taskState);
33
	}
34
35
	/**
36
	* Mark given task complete in XML
37
	*
38
	* @param  string $xml Parsed XML
39
	* @param  string $id  Task's ID
40
	* @return string      Updated XML
41
	*/
42 6
	public static function setTaskComplete(string $xml, string $id): string
43
	{
44 6
		return self::setTaskState($xml, $id, 'complete', 'x');
45
	}
46
47
	/**
48
	* Mark given task incomplete in XML
49
	*
50
	* @param  string $xml Parsed XML
51
	* @param  string $id  Task's ID
52
	* @return string      Updated XML
53
	*/
54 1
	public static function setTaskIncomplete(string $xml, string $id): string
55
	{
56 1
		return self::setTaskState($xml, $id, 'incomplete', ' ');
57
	}
58
59
	/**
60
	* Change the state and marker of given task in XML
61
	*
62
	* @param  string $xml    Parsed XML
63
	* @param  string $id     Task's ID
64
	* @param  string $state  Task's state ("complete" or "incomplete")
65
	* @param  string $marker Task marker ("x" or " ")
66
	* @return string         Updated XML
67
	*/
68 7
	protected static function setTaskState(string $xml, string $id, string $state, string $marker): string
69
	{
70 7
		return preg_replace_callback(
71 7
			'(<TASK(?: [^=]++="[^"]*+")*? id="' . $id . '"\\K([^>]*+)>[^<]*+(?=</TASK>))',
72
			function ($m) use ($state, $marker)
73
			{
74 5
				preg_match_all('( ([^=]++)="[^"]*+")', $m[1], $m);
75
76 5
				$attributes = array_combine($m[1], $m[0]);
77 5
				$attributes['state'] = ' state="' . $state . '"';
78 5
				ksort($attributes);
1 ignored issue
show
Bug introduced by
It seems like $attributes can also be of type false; however, parameter $array of ksort() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

78
				ksort(/** @scrutinizer ignore-type */ $attributes);
Loading history...
79
80 5
				return implode('', $attributes) . '>[' . $marker . ']';
81 7
			},
82
			$xml
83
		);
84
	}
85
86
	/**
87
	* Return stats from a parsed representation
88
	*
89
	* @param  string $xml Parsed XML
90
	* @return array       Number of "complete" and "incomplete" tasks
91
	*/
92 3
	public static function getStats(string $xml): array
93
	{
94 3
		$stats = ['complete' => 0, 'incomplete' => 0];
95
96 3
		preg_match_all('(<TASK(?: [^=]++="[^"]*+")*? state="\\K\\w++)', $xml, $m);
97 3
		foreach ($m[0] as $state)
98
		{
99 2
			if (!isset($stats[$state]))
100
			{
101 1
				$stats[$state] = 0;
102
			}
103 2
			++$stats[$state];
104
		}
105
106 3
		return $stats;
107
	}
108
}