1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8namespace Tiki\Yaml;
9
10use Tiki\Yaml\Filter\FilterInterface;
11
12class Directives
13{
14	protected $path;
15	protected $filter;
16
17	public function __construct(FilterInterface $filter = null, $path = null)
18	{
19		if (is_null($path)) {
20			$this->path = TIKI_PATH;
21		} else {
22			$this->path = $path;
23		}
24
25		$this->filter = $filter;
26	}
27
28	public function setPath($path)
29	{
30		$this->path = $path;
31	}
32
33	public function getPath()
34	{
35		return $this->path;
36	}
37
38	protected function applyDirective($directive, &$value, $key)
39	{
40		$class = "\\Tiki\\Yaml\\Directive\\Directive" . ucfirst($directive);
41		if (! class_exists($class, true)) {
42			return;
43		}
44		$directive = new $class();
45		$directive->process($value, $key, ['path' => $this->path]);
46	}
47
48	protected function directiveFromValue($value)
49	{
50		if (is_array($value)) {
51			$value = array_values($value)[0];
52		}
53		$directive = substr($value, 1, strpos($value, " ") - 1);
54		return $directive;
55	}
56
57	protected function valueIsDirective($value)
58	{
59		$testValue = $value;
60		if (is_array($value) && ! empty($value)) {
61			$testValue = array_values($value)[0];
62		}
63
64		if (is_string($testValue) && (strncmp('!', $testValue, 1) == 0)) {
65			// Wiki syntax can often start with ! for titles and so the following checks are needed to reduce
66			// conflict possibility with YAML user-defined data type extensions syntax
67			if (! ctype_lower(substr($testValue, 1, 1))) {
68				return false;
69			}
70
71			$class = "\\Tiki\\Yaml\\Directive\\Directive" . ucfirst($this->directiveFromValue($testValue));
72			if (! class_exists($class)) {
73				return false;
74			}
75
76			return true;
77		}
78
79		return false;
80	}
81
82	protected function map(&$value, $key)
83	{
84		if ($this->valueIsDirective($value)) {
85			if ($this->filter instanceof FilterInterface) {
86				$this->filter->filter($value);
87			}
88			$this->applyDirective($this->directiveFromValue($value), $value, $key);
89		} else {
90			if (is_array($value)) {
91				array_walk($value, [$this, "map"]);
92			}
93		}
94	}
95
96	public function process(&$yaml)
97	{
98		array_walk($yaml, [$this, "map"]);
99	}
100}
101