Commit | Line | Data |
---|---|---|
19b53e5b C |
1 | <?php |
2 | ||
380f3545 TO |
3 | /* |
4 | +--------------------------------------------------------------------+ | |
41498ac5 | 5 | | Copyright CiviCRM LLC. All rights reserved. | |
380f3545 | 6 | | | |
41498ac5 TO |
7 | | This work is published under the GNU AGPLv3 license with some | |
8 | | permitted exceptions and without any warranty. For full license | | |
9 | | and copyright information, see https://civicrm.org/licensing | | |
380f3545 TO |
10 | +--------------------------------------------------------------------+ |
11 | */ | |
12 | ||
19b53e5b C |
13 | namespace Civi\Api4\Action; |
14 | ||
15 | use Civi\API\Exception\NotImplementedException; | |
16 | use Civi\Api4\Generic\BasicGetAction; | |
19b53e5b C |
17 | use Civi\Api4\Utils\ReflectionUtils; |
18 | ||
19 | /** | |
fc95d9a5 CW |
20 | * Get all API actions for the $ENTITY entity. |
21 | * | |
22 | * Includes a list of accepted parameters for each action, descriptions and other documentation. | |
19b53e5b C |
23 | */ |
24 | class GetActions extends BasicGetAction { | |
25 | ||
26 | private $_actions = []; | |
27 | ||
28 | private $_actionsToGet; | |
29 | ||
30 | protected function getRecords() { | |
31 | $this->_actionsToGet = $this->_itemsToGet('name'); | |
32 | ||
33 | $entityReflection = new \ReflectionClass('\Civi\Api4\\' . $this->_entityName); | |
34 | foreach ($entityReflection->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC) as $method) { | |
35 | $actionName = $method->getName(); | |
449c4e6b | 36 | if ($actionName != 'permissions' && $actionName != 'getInfo' && $actionName[0] != '_') { |
e15f9453 | 37 | $this->loadAction($actionName, $method); |
19b53e5b C |
38 | } |
39 | } | |
40 | if (!$this->_actionsToGet || count($this->_actionsToGet) > count($this->_actions)) { | |
23c2d07c | 41 | // Search for entity-specific actions in extensions |
19b53e5b C |
42 | foreach (\CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles() as $ext) { |
43 | $dir = \CRM_Utils_File::addTrailingSlash(dirname($ext['filePath'])); | |
44 | $this->scanDir($dir . 'Civi/Api4/Action/' . $this->_entityName); | |
45 | } | |
23c2d07c | 46 | // Search for entity-specific actions in core |
47 | $this->scanDir(\CRM_Utils_File::addTrailingSlash(__DIR__) . $this->_entityName); | |
19b53e5b C |
48 | } |
49 | ksort($this->_actions); | |
50 | return $this->_actions; | |
51 | } | |
52 | ||
53 | /** | |
54 | * @param $dir | |
55 | */ | |
56 | private function scanDir($dir) { | |
57 | if (is_dir($dir)) { | |
58 | foreach (glob("$dir/*.php") as $file) { | |
59 | $matches = []; | |
3ba93c64 | 60 | preg_match('/(\w*)\.php$/', $file, $matches); |
19b53e5b C |
61 | $actionName = array_pop($matches); |
62 | $actionClass = new \ReflectionClass('\\Civi\\Api4\\Action\\' . $this->_entityName . '\\' . $actionName); | |
63 | if ($actionClass->isInstantiable() && $actionClass->isSubclassOf('\\Civi\\Api4\\Generic\\AbstractAction')) { | |
64 | $this->loadAction(lcfirst($actionName)); | |
65 | } | |
66 | } | |
67 | } | |
68 | } | |
69 | ||
70 | /** | |
71 | * @param $actionName | |
e15f9453 | 72 | * @param \ReflectionMethod $method |
19b53e5b | 73 | */ |
e15f9453 | 74 | private function loadAction($actionName, $method = NULL) { |
19b53e5b C |
75 | try { |
76 | if (!isset($this->_actions[$actionName]) && (!$this->_actionsToGet || in_array($actionName, $this->_actionsToGet))) { | |
3a8dc228 | 77 | $action = \Civi\API\Request::create($this->getEntityName(), $actionName, ['version' => 4]); |
7e67fdb7 | 78 | if (is_object($action) && (!$this->checkPermissions || $action->isAuthorized())) { |
19b53e5b | 79 | $this->_actions[$actionName] = ['name' => $actionName]; |
e15f9453 | 80 | if ($this->_isFieldSelected('description', 'comment', 'see')) { |
e3c6d5ff | 81 | $vars = ['entity' => $this->getEntityName(), 'action' => $actionName]; |
e15f9453 | 82 | // Docblock from action class |
fc95d9a5 | 83 | $actionDocs = ReflectionUtils::getCodeDocs($action->reflect(), NULL, $vars); |
e15f9453 CW |
84 | unset($actionDocs['method']); |
85 | // Docblock from action factory function in entity class. This takes precedence since most action classes are generic. | |
86 | if ($method) { | |
fc95d9a5 CW |
87 | $methodDocs = ReflectionUtils::getCodeDocs($method, 'Method', $vars); |
88 | // Allow method doc to inherit class doc | |
89 | if (strpos($method->getDocComment(), '@inheritDoc') !== FALSE && !empty($methodDocs['comment']) && !empty($actionDocs['comment'])) { | |
90 | $methodDocs['comment'] .= "\n\n" . $actionDocs['comment']; | |
91 | } | |
92 | $actionDocs = array_filter($methodDocs) + $actionDocs; | |
e15f9453 CW |
93 | } |
94 | $this->_actions[$actionName] += $actionDocs; | |
19b53e5b C |
95 | } |
96 | if ($this->_isFieldSelected('params')) { | |
97 | $this->_actions[$actionName]['params'] = $action->getParamInfo(); | |
98 | // Language param is only relevant on multilingual sites | |
99 | $languageLimit = (array) \Civi::settings()->get('languageLimit'); | |
100 | if (count($languageLimit) < 2) { | |
101 | unset($this->_actions[$actionName]['params']['language']); | |
102 | } | |
103 | elseif (isset($this->_actions[$actionName]['params']['language'])) { | |
104 | $this->_actions[$actionName]['params']['language']['options'] = array_keys($languageLimit); | |
105 | } | |
106 | } | |
107 | } | |
108 | } | |
109 | } | |
110 | catch (NotImplementedException $e) { | |
111 | } | |
112 | } | |
113 | ||
114 | public function fields() { | |
115 | return [ | |
116 | [ | |
117 | 'name' => 'name', | |
e15f9453 | 118 | 'description' => 'Action name', |
19b53e5b C |
119 | ], |
120 | [ | |
121 | 'name' => 'description', | |
e15f9453 | 122 | 'description' => 'Description from docblock', |
19b53e5b C |
123 | ], |
124 | [ | |
125 | 'name' => 'comment', | |
e15f9453 CW |
126 | 'description' => 'Comments from docblock', |
127 | ], | |
128 | [ | |
129 | 'name' => 'see', | |
130 | 'data_type' => 'Array', | |
131 | 'description' => 'Any @see annotations from docblock', | |
19b53e5b C |
132 | ], |
133 | [ | |
134 | 'name' => 'params', | |
e15f9453 | 135 | 'description' => 'List of all accepted parameters', |
19b53e5b C |
136 | 'data_type' => 'Array', |
137 | ], | |
138 | ]; | |
139 | } | |
140 | ||
141 | } |