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
8class Search_Action_ActionStep implements Search_Action_Step
9{
10	private $action;
11	private $definition;
12
13	function __construct(Search_Action_Action $action, array $definition)
14	{
15		$this->action = $action;
16		$this->definition = $definition;
17	}
18
19	function getFields()
20	{
21		$initial = [];
22		foreach (array_keys($this->action->getValues()) as $keyName) {
23			$initial[] = rtrim($keyName, '+');
24		}
25
26		$required = [];
27		$found = [];
28
29		foreach ($this->definition as $key => $value) {
30			if (preg_match('/^(.*)_field$/', $key, $parts)) {
31				$key = $parts[1];
32
33				if (in_array($key, $initial)) {
34					$required[] = $value;
35					$initial = array_diff($initial, [$key]);
36				}
37			} elseif (preg_match('/^(.*)_field_(coalesce|multiple)$/', $key, $parts)) {
38				$key = $parts[1];
39
40				if (in_array($key, $initial)) {
41					$required = array_merge($required, $this->splitFields($value));
42					$initial = array_diff($initial, [$key]);
43				}
44			} else {
45				$found[] = $key;
46			}
47		}
48
49		return array_diff(array_merge($initial, $required), $found);
50	}
51
52	function validate(array $entry)
53	{
54		if ($entry = $this->prepare($entry)) {
55			return $this->action->validate($entry);
56		}
57
58		return false;
59	}
60
61	function execute(array $entry)
62	{
63		if ($entry = $this->prepare($entry)) {
64			return $this->action->execute($entry);
65		}
66
67		return false;
68	}
69
70	function requiresInput()
71	{
72		return $this->action->requiresInput(new JitFilter($this->definition));
73	}
74
75	private function prepare($entry)
76	{
77		$out = [];
78
79		foreach ($this->action->getValues() as $fieldName => $isRequired) {
80			$initialName = $fieldName;
81			$fieldName = rtrim($fieldName, '+');
82			$requiresArray = $initialName != $fieldName;
83
84			$values = [];
85
86			if (isset($this->definition[$fieldName])) {
87				// Static value
88				$values = [$this->definition[$fieldName]];
89			} elseif (isset($this->definition[$fieldName . '_field'])) {
90				// Use different field
91				$values = $this->readValues($entry, [$this->definition[$fieldName . '_field']]);
92			} elseif (isset($this->definition[$fieldName . '_field_coalesce'])) {
93				$readFrom = $this->splitFields($this->definition[$fieldName . '_field_coalesce']);
94				$values = $this->readValues($entry, $readFrom);
95				$values = array_slice($values, 0, 1);
96			} elseif (isset($this->definition[$fieldName . '_field_multiple'])) {
97				$readFrom = $this->splitFields($this->definition[$fieldName . '_field_multiple']);
98				$values = $this->readValues($entry, $readFrom);
99			} else {
100				$values = $this->readValues($entry, [$fieldName]);
101			}
102
103			if (empty($values) && $isRequired) {
104				throw new Search_Action_Exception(tr('Missing required action parameter or value: %0', $fieldName));
105			} elseif ($requiresArray) {
106				$out[$fieldName] = $values;
107			} else {
108				$out[$fieldName] = empty($values) ? null : reset($values);
109			}
110		}
111
112		return new JitFilter($out);
113	}
114
115	private function readValues($entry, $readFrom)
116	{
117		$values = [];
118
119		foreach ($readFrom as $candidate) {
120			if (isset($entry[$candidate])) {
121				$values[] = $entry[$candidate];
122			}
123		}
124
125		return $values;
126	}
127
128	private function splitFields($string)
129	{
130		return array_filter(array_map('trim', explode(',', $string)));
131	}
132}
133