Last active
March 22, 2021 13:40
-
-
Save 123andy/dd262439c0478ffbd37e4685bc8017ac to your computer and use it in GitHub Desktop.
Custom Action Tag to convert "Andy's Hook Framework" things into External Modules
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Stanford\Utility; | |
use \REDCap as REDCap; | |
/** | |
* Class ActionTagHelper | |
* | |
* A class for helping to parse custom action tags | |
*/ | |
class ActionTagHelper | |
{ | |
// Cache the search results to speed complex queries or queries with many hooks | |
static $cache = array(); | |
/** | |
* This is a utility function to return action tags, fields, and parameters for specific action-tag scripts | |
* | |
* @param null $tags a single or array of action_tags that you are looking for | |
* @param null $fields a single or array of fields that you want to look in | |
* @param null $instruments a single or array of instruments to look in | |
* @throws \Exception | |
* @return array array( "tag1" => array( | |
* "field_name" => array( | |
* "params" => any parameters next to tag (supports string, list, or json | |
* ) | |
* ) | |
*/ | |
static function getActionTags($tags = NULL, $fields = NULL, $instruments = NULL) { | |
// Check to see if this search has been cached | |
$arg_key = md5(json_encode(func_get_args())); | |
if (isset(self::$cache[$arg_key])) { | |
// \Plugin::log($arg_key, "DEBUG", "Using Cache"); | |
return self::$cache[$arg_key]; | |
} | |
// Convert tag_filter into uppercase array | |
if (!empty($tags)) { | |
if (!is_array($tags)) $tags = array($tags); | |
$tags = array_map('strtoupper', $tags); | |
} | |
// \Plugin::log($tag_filter,"DEBUG","tag filter "); | |
// Get the metadata with applied filters | |
$q = REDCap::getDataDictionary('json', false, $fields, $instruments); | |
$metadata = json_decode($q,true); | |
// \Plugin::log($metadata,"DEBUG","Metadata"); | |
// Build a backwards-compatible action_tag array | |
$action_tags = array(); | |
foreach ($metadata as $field) { | |
$field_name = $field['field_name']; | |
$field_annotation = $field['field_annotation']; | |
$parsed_tags = self::parseActionTags($field_annotation); | |
// \Plugin::log($tags, "DEBUG", "TAGS for $field_name"); | |
foreach ($parsed_tags as $tag) { | |
// All action-tags should be parsed as uppercase | |
$action_tag = strtoupper($tag['actiontag']); | |
// If we are filtering, skip non-specified tags | |
if ($tags AND !in_array($action_tag, $tags)) continue; | |
// Initialize the action_tag node | |
if (!isset($action_tags[$action_tag])) $action_tags[$action_tag] = array(); | |
// Merge action_tag into action_tags (I know this syntax sucks, but it is legacy so we're leaving it for now... | |
$action_tags[$action_tag] = array_merge( $action_tags[$action_tag], | |
array( | |
$field_name => array( | |
'params' => isset($tag['params']) ? $tag['params'] : "" | |
) | |
) | |
); | |
} | |
} | |
// Cache this search | |
self::$cache[$arg_key] = $action_tags; | |
return $action_tags; | |
} | |
/** | |
* Parses a string for arrays of actiontags (optionally filtering by the supplied tag) | |
* Examples of valid action tags are: | |
* @TAG1 | |
* @TAG2=1,2,3 | |
* @TAG3={ | |
* "key":"value", | |
* "key2","value2" | |
* } | |
* | |
* The results are an array where each match is an actiontag with a key of | |
* [0] => [ | |
* "actiontag" => "@TAG1" | |
* ], | |
* [1] => [ | |
* "actiontag" => "@TAG2", | |
* "params" => "1,2,3" | |
* ], | |
* [2] => [ | |
* "actiontag" => "@TAG3", | |
* "params" => "{"key":"value","key2","value2"} | |
* | |
* https://regex101.com/r/fL2rM8/5 | |
* | |
* @param $string The string to be parsed for actiontags (in the format of <code>@FOO=BAR or @FOO={"param":"bar"}</code> | |
* @param null $tag_only If you wish to select a single tag | |
* @return array|bool returns the match array with the key equal to the tag and an array containing keys of 'params, params_json and params_text' | |
*/ | |
static function parseActionTags($string, $tag_only = null) { | |
$re = "/(?(DEFINE) | |
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? ) | |
(?<boolean> true | false | null ) | |
(?<string> \" ([^\"\\\\]* | \\\\ [\"\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* \" ) | |
(?<array> \[ (?: (?&json) (?: , (?&json) )* )? \s* \] ) | |
(?<pair> \s* (?&string) \s* : (?&json) ) | |
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} ) | |
(?<fieldname> [a-zA-Z0-9\_\-]+ ) | |
(?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) ) | |
(?<fieldlist> (?: (?&fieldname) (?: , (?&fieldname) )+ )+ ) | |
) | |
(?'actiontag' | |
\@(?&fieldname) | |
) | |
(?:\= | |
(?'params' | |
(?: | |
(?'match_list'(?&fieldlist)) | |
| | |
(?'match_json'(?&json)) | |
| | |
(?'match_string'(?:[[:alnum:]\_\-]+)) | |
) | |
) | |
)?/ixm"; | |
preg_match_all($re, $string, $matches); | |
// Return false if none are found | |
if (count($matches['actiontag']) == 0) return false; | |
$results = array(); | |
foreach ($matches['actiontag'] as $i => $tag) { | |
$tag = strtoupper($tag); | |
if ($tag_only && ($tag != strtoupper($tag_only))) continue; | |
$results[] = array( | |
'actiontag' => $tag, | |
'params' => $matches['params'][$i] | |
); | |
} | |
return $results; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment