4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
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 |
10 +--------------------------------------------------------------------+
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
22 namespace Civi\Api4\Action
;
24 use Civi\API\Exception\NotImplementedException
;
25 use Civi\Api4\Generic\BasicGetAction
;
26 use Civi\Api4\Utils\ActionUtil
;
27 use Civi\Api4\Utils\ReflectionUtils
;
30 * Get all API actions for the $ENTITY entity.
32 * Includes a list of accepted parameters for each action, descriptions and other documentation.
34 class GetActions
extends BasicGetAction
{
36 private $_actions = [];
38 private $_actionsToGet;
40 protected function getRecords() {
41 $this->_actionsToGet
= $this->_itemsToGet('name');
43 $entityReflection = new \
ReflectionClass('\Civi\Api4\\' . $this->_entityName
);
44 foreach ($entityReflection->getMethods(\ReflectionMethod
::IS_STATIC | \ReflectionMethod
::IS_PUBLIC
) as $method) {
45 $actionName = $method->getName();
46 if ($actionName != 'permissions' && $actionName[0] != '_') {
47 $this->loadAction($actionName, $method);
50 if (!$this->_actionsToGet ||
count($this->_actionsToGet
) > count($this->_actions
)) {
51 // Search for entity-specific actions in extensions
52 foreach (\CRM_Extension_System
::singleton()->getMapper()->getActiveModuleFiles() as $ext) {
53 $dir = \CRM_Utils_File
::addTrailingSlash(dirname($ext['filePath']));
54 $this->scanDir($dir . 'Civi/Api4/Action/' . $this->_entityName
);
56 // Search for entity-specific actions in core
57 $this->scanDir(\CRM_Utils_File
::addTrailingSlash(__DIR__
) . $this->_entityName
);
59 ksort($this->_actions
);
60 return $this->_actions
;
66 private function scanDir($dir) {
68 foreach (glob("$dir/*.php") as $file) {
70 preg_match('/(\w*).php/', $file, $matches);
71 $actionName = array_pop($matches);
72 $actionClass = new \
ReflectionClass('\\Civi\\Api4\\Action\\' . $this->_entityName
. '\\' . $actionName);
73 if ($actionClass->isInstantiable() && $actionClass->isSubclassOf('\\Civi\\Api4\\Generic\\AbstractAction')) {
74 $this->loadAction(lcfirst($actionName));
82 * @param \ReflectionMethod $method
84 private function loadAction($actionName, $method = NULL) {
86 if (!isset($this->_actions
[$actionName]) && (!$this->_actionsToGet ||
in_array($actionName, $this->_actionsToGet
))) {
87 $action = ActionUtil
::getAction($this->getEntityName(), $actionName);
88 if (is_object($action)) {
89 $this->_actions
[$actionName] = ['name' => $actionName];
90 if ($this->_isFieldSelected('description', 'comment', 'see')) {
91 $vars = ['entity' => $this->getEntityName(), 'action' => $actionName];
92 // Docblock from action class
93 $actionDocs = ReflectionUtils
::getCodeDocs($action->reflect(), NULL, $vars);
94 unset($actionDocs['method']);
95 // Docblock from action factory function in entity class. This takes precedence since most action classes are generic.
97 $methodDocs = ReflectionUtils
::getCodeDocs($method, 'Method', $vars);
98 // Allow method doc to inherit class doc
99 if (strpos($method->getDocComment(), '@inheritDoc') !== FALSE && !empty($methodDocs['comment']) && !empty($actionDocs['comment'])) {
100 $methodDocs['comment'] .= "\n\n" . $actionDocs['comment'];
102 $actionDocs = array_filter($methodDocs) +
$actionDocs;
104 $this->_actions
[$actionName] +
= $actionDocs;
106 if ($this->_isFieldSelected('params')) {
107 $this->_actions
[$actionName]['params'] = $action->getParamInfo();
108 // Language param is only relevant on multilingual sites
109 $languageLimit = (array) \Civi
::settings()->get('languageLimit');
110 if (count($languageLimit) < 2) {
111 unset($this->_actions
[$actionName]['params']['language']);
113 elseif (isset($this->_actions
[$actionName]['params']['language'])) {
114 $this->_actions
[$actionName]['params']['language']['options'] = array_keys($languageLimit);
120 catch (NotImplementedException
$e) {
124 public function fields() {
128 'description' => 'Action name',
131 'name' => 'description',
132 'description' => 'Description from docblock',
136 'description' => 'Comments from docblock',
140 'data_type' => 'Array',
141 'description' => 'Any @see annotations from docblock',
145 'description' => 'List of all accepted parameters',
146 'data_type' => 'Array',