Commit | Line | Data |
---|---|---|
19b53e5b C |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | CiviCRM version 4.7 | | |
5 | +--------------------------------------------------------------------+ | |
6 | | Copyright CiviCRM LLC (c) 2004-2015 | | |
7 | +--------------------------------------------------------------------+ | |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | ||
28 | namespace Civi\Api4\Provider; | |
29 | ||
30 | use Civi\API\Event\ResolveEvent; | |
31 | use Civi\API\Provider\ProviderInterface; | |
32 | use Civi\Api4\Generic\AbstractAction; | |
33 | use Civi\API\Events; | |
34 | use Civi\Api4\Utils\ReflectionUtils; | |
35 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
36 | ||
37 | /** | |
38 | * Accept $apiRequests based on \Civi\API\Action | |
39 | */ | |
40 | class ActionObjectProvider implements EventSubscriberInterface, ProviderInterface { | |
41 | ||
42 | /** | |
43 | * @return array | |
44 | */ | |
45 | public static function getSubscribedEvents() { | |
46 | // Using a high priority allows adhoc implementations | |
47 | // to override standard implementations -- which is | |
48 | // handy for testing/mocking. | |
49 | return [ | |
50 | Events::RESOLVE => [ | |
51 | ['onApiResolve', Events::W_EARLY], | |
52 | ], | |
53 | ]; | |
54 | } | |
55 | ||
56 | /** | |
57 | * @param \Civi\API\Event\ResolveEvent $event | |
58 | * API resolution event. | |
59 | */ | |
60 | public function onApiResolve(ResolveEvent $event) { | |
61 | $apiRequest = $event->getApiRequest(); | |
62 | if ($apiRequest instanceof AbstractAction) { | |
63 | $event->setApiRequest($apiRequest); | |
64 | $event->setApiProvider($this); | |
65 | $event->stopPropagation(); | |
66 | } | |
67 | } | |
68 | ||
69 | /** | |
70 | * @inheritDoc | |
71 | * | |
72 | * @param \Civi\Api4\Generic\AbstractAction $action | |
73 | * | |
74 | * @return \Civi\Api4\Generic\Result | |
75 | */ | |
76 | public function invoke($action) { | |
77 | // Load result class based on @return annotation in the execute() method. | |
78 | $reflection = new \ReflectionClass($action); | |
79 | $doc = ReflectionUtils::getCodeDocs($reflection->getMethod('execute'), 'Method'); | |
80 | $resultClass = \CRM_Utils_Array::value('return', $doc, '\\Civi\\Api4\\Generic\\Result'); | |
81 | $result = new $resultClass(); | |
82 | $result->action = $action->getActionName(); | |
83 | $result->entity = $action->getEntityName(); | |
84 | $action->_run($result); | |
85 | $this->handleChains($action, $result); | |
86 | return $result; | |
87 | } | |
88 | ||
89 | /** | |
90 | * Run each chained action once per row | |
91 | * | |
92 | * @param \Civi\Api4\Generic\AbstractAction $action | |
93 | * @param \Civi\Api4\Generic\Result $result | |
94 | */ | |
95 | protected function handleChains($action, $result) { | |
96 | foreach ($action->getChain() as $name => $request) { | |
97 | $request += [NULL, NULL, [], NULL]; | |
98 | $request[2]['checkPermissions'] = $action->getCheckPermissions(); | |
99 | foreach ($result as &$row) { | |
100 | $row[$name] = $this->runChain($request, $row); | |
101 | } | |
102 | } | |
103 | } | |
104 | ||
105 | /** | |
106 | * Run a chained action | |
107 | * | |
108 | * @param $request | |
109 | * @param $row | |
110 | * @return array|\Civi\Api4\Generic\Result|null | |
111 | * @throws \API_Exception | |
112 | */ | |
113 | protected function runChain($request, $row) { | |
114 | list($entity, $action, $params, $index) = $request; | |
115 | // Swap out variables in $entity, $action & $params | |
116 | $this->resolveChainLinks($entity, $row); | |
117 | $this->resolveChainLinks($action, $row); | |
118 | $this->resolveChainLinks($params, $row); | |
119 | return (array) civicrm_api4($entity, $action, $params, $index); | |
120 | } | |
121 | ||
122 | /** | |
123 | * Swap out variable names | |
124 | * | |
125 | * @param mixed $val | |
126 | * @param array $result | |
127 | */ | |
128 | protected function resolveChainLinks(&$val, $result) { | |
129 | if (is_array($val)) { | |
130 | foreach ($val as &$v) { | |
131 | $this->resolveChainLinks($v, $result); | |
132 | } | |
133 | } | |
134 | elseif (is_string($val) && strlen($val) > 1 && substr($val, 0, 1) === '$') { | |
135 | $val = \CRM_Utils_Array::pathGet($result, explode('.', substr($val, 1))); | |
136 | } | |
137 | } | |
138 | ||
139 | /** | |
140 | * @inheritDoc | |
141 | * @param int $version | |
142 | * @return array | |
143 | */ | |
144 | public function getEntityNames($version) { | |
145 | /** FIXME */ | |
146 | return []; | |
147 | } | |
148 | ||
149 | /** | |
150 | * @inheritDoc | |
151 | * @param int $version | |
152 | * @param string $entity | |
153 | * @return array | |
154 | */ | |
155 | public function getActionNames($version, $entity) { | |
156 | /** FIXME Civi\API\V4\Action\GetActions */ | |
157 | return []; | |
158 | } | |
159 | ||
160 | } |