From 7d16f66dc43cadcb2cbf2af3d0b4830d53750ef4 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Thu, 25 Oct 2018 10:54:55 +1100 Subject: [PATCH] dev/core#472 Allow for APIv3 to find examples in Extenion folders as well as core Improve inclusion scanning by using get_include_path as suggested by Coleamn and alpha sort the list of entities Deal with windows directory separators and more helpfully handle the trailing and non trailing slash directories Further fixes for windows Directory Separators --- CRM/Admin/Page/APIExplorer.php | 65 ++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/CRM/Admin/Page/APIExplorer.php b/CRM/Admin/Page/APIExplorer.php index 678cef4a8f48..9d5cd46c9a9c 100644 --- a/CRM/Admin/Page/APIExplorer.php +++ b/CRM/Admin/Page/APIExplorer.php @@ -36,6 +36,30 @@ */ class CRM_Admin_Page_APIExplorer extends CRM_Core_Page { + /** + * Return unique paths for checking for examples. + * @return array + */ + private static function uniquePaths() { + // Ensure that paths with trailing slashes are properly dealt with + $paths = explode(PATH_SEPARATOR, get_include_path()); + foreach ($paths as $id => $rawPath) { + $pathParts = explode(DIRECTORY_SEPARATOR, $rawPath); + foreach ($pathParts as $partId => $part) { + if (empty($part)) { + unset($pathParts[$partId]); + } + } + $newRawPath = implode(DIRECTORY_SEPARATOR, $pathParts); + if ($newRawPath != $rawPath) { + $paths[$id] = DIRECTORY_SEPARATOR . $newRawPath; + } + } + $paths = array_unique($paths); + return $paths; + } + + /** * Run page. * @@ -51,12 +75,20 @@ public function run() { $this->assign('operators', CRM_Core_DAO::acceptedSQLOperators()); // List example directories + // use get_include_path to ensure that extensions are captured. $examples = array(); - foreach (scandir(\Civi::paths()->getPath('[civicrm.root]/api/v3/examples')) as $item) { - if ($item && strpos($item, '.') === FALSE) { - $examples[] = $item; + $paths = self::uniquePaths(); + foreach ($paths as $path) { + $dir = \CRM_Utils_File::addTrailingSlash($path) . 'api' . DIRECTORY_SEPARATOR . 'v3' . DIRECTORY_SEPARATOR . 'examples'; + if (is_dir($dir)) { + foreach (scandir($dir) as $item) { + if ($item && strpos($item, '.') === FALSE && array_search($item, $examples) === FALSE) { + $examples[] = $item; + } + } } } + sort($examples); $this->assign('examples', $examples); return parent::run(); @@ -78,20 +110,31 @@ public function userContext() { public static function getExampleFile() { if (!empty($_GET['entity']) && strpos($_GET['entity'], '.') === FALSE) { $examples = array(); - foreach (scandir(\Civi::paths()->getPath("[civicrm.root]/api/v3/examples/{$_GET['entity']}")) as $item) { - $item = str_replace('.php', '', $item); - if ($item && strpos($item, '.') === FALSE) { - $examples[] = array('key' => $item, 'value' => $item); + $paths = self::uniquePaths(); + foreach ($paths as $path) { + $dir = \CRM_Utils_File::addTrailingSlash($path) . 'api' . DIRECTORY_SEPARATOR . 'v3' . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $_GET['entity']; + if (is_dir($dir)) { + foreach (scandir($dir) as $item) { + $item = str_replace('.php', '', $item); + if ($item && strpos($item, '.') === FALSE) { + $examples[] = array('key' => $item, 'value' => $item); + } + } } } CRM_Utils_JSON::output($examples); } if (!empty($_GET['file']) && strpos($_GET['file'], '.') === FALSE) { - $fileName = \Civi::paths()->getPath("[civicrm.root]/api/v3/examples/{$_GET['file']}.php"); - if (file_exists($fileName)) { - echo file_get_contents($fileName); + $paths = self::uniquePaths(); + $fileFound = FALSE; + foreach ($paths as $path) { + $fileName = \CRM_Utils_File::addTrailingSlash($path) . 'api' . DIRECTORY_SEPARATOR . 'v3' . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $_GET['file'] . '.php'; + if (!$fileFound && file_exists($fileName)) { + $fileFound = TRUE; + echo file_get_contents($fileName); + } } - else { + if (!$fileFound) { echo "Not found."; } CRM_Utils_System::civiExit();