获取标签包含的缓存标识
@access public
@param  string $tag 缓存标签
@return array
194826
public function getTagItems(string $tag): array
    {
        $tagName = $this->getTagKey($tag);
        return explode(',', $this->handler->get($tagName));
    }
121567
public function getTagged($tag)
	{
		$services = array();

		if (isset($this->tags[$tag]))
		{
			foreach ($this->tags[$tag] as $service)
			{
				$services[] = $this->get($service);
			}
		}

		return $services;
	}
403839
public function get($tag)
    {
        // load if necessary
        if (!$this->loaded) {
            $this->load();
        }

        // get tag
        if (!isset($this->phrases[$tag]) || $this->phrases[$tag] == '') {
            return 'LOCALIZE [' . $this->local . ']: ' . $tag;
        } else {
            return $this->phrases[$tag];
        }
    }
824404
private function _parseTag($tag)
        {   
//          return nothing if the tag is disabled
            if(isset($tag['attributes']->disabled) === true && $tag['attributes']->disabled === 'true')
            {
                return '';
            }
            
            $tag_data = false;
            $caching_tag = isset($tag['attributes']->cache) && $tag['attributes']->cache === 'false' ? false : true;
            if($this->_options['cache_tags'] === true && $caching_tag === true)
            {
                if($this->_options['custom_cache_tag_class'] !== false)
                {
                    $tag_data = call_user_func_array(array($this->_options['custom_cache_tag_class'], 'getCache'), array($tag));
                }
                else 
                {
                    $cache_file = $this->_options['cache_directory'].md5(serialize($tag));
                    if(is_file($cache_file) === true)
                    {
                        $tag_data = file_get_contents($cache_file);
                    }
                }
                if($tag_data)
                {
                    $tag['cached'] = true;
                    return $tag_data;
                }
            }    
            
//          look for and load tag function file
            $tag_func_name = ucwords(str_replace(array('_', '-'), ' ', $tag['name']));
            $tag_func_name = strtolower(substr($tag_func_name, 0, 1)).substr($tag_func_name, 1);
            $func_name = str_replace(' ', '', $this->_options['tag_callback_prefix'].$tag_func_name);
            $tag_data = '';
            $collect_tag = false;
            $tag_order = false;
            if(function_exists($func_name) === false)
            {
                $has_resource = false;
                if(is_array($this->_options['tag_directory']) === false)
                {
                    $this->_options['tag_directory'] = array($this->_options['tag_directory']);
                }
                foreach ($this->_options['tag_directory'] as $directory)
                {
                    $tag_file = rtrim($directory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$tag['name'].DIRECTORY_SEPARATOR.'tag.php';
                    if(is_file($tag_file) === true)
                    {
                        if(isset(self::$_required[$tag['name']]) === false)
                        {
                            self::$_required[$tag['name']] = true;
                            $collect = false;
                            if(function_exists($func_name) === false)
                            {
                                include_once $tag_file;
                            }
                            self::$_tags_to_collect[$tag['name']] = $collect;
                            if(function_exists($func_name) === false)
                            {
                                return self::throwError($tag['name'], 'tag resource "'.$directory.DIRECTORY_SEPARATOR.'tag.php" found but callback "'.$func_name.'" wasn\'t.');
                            }
                            $has_resource = true;
                        }
                    }
                }
                if($has_resource === false)
                {
                    return self::throwError($tag['name'], 'tag resource not found.');
                } 
            }
            
//          do we have to collect this tag for parsing at a later point
            if(self::$_tags_to_collect[$tag['name']] !== false)
            {
                if(isset(self::$tag_collections[$tag['name']]) === false)
                {
                    self::$tag_collections[$tag['name']] = array();
                }
                $tag['collected'] = true;
                $index = array_push(self::$tag_collections[$tag['name']], $tag)-1;
                if($tag_order !== false)
                {
                    if(isset(self::$_tag_order[$block['name']]) === false)
                    {
                        self::$_tag_order[$block['name']] = array();
                    }
                    self::$_tag_order[$block['name']] = $tag_order;
                }
                return self::$tag_collections[$tag['name']][$index]['tag'] = '------@@%'.self::$_instance.'-'.$tag['name'].'-'.$index.'-'.uniqid(time().'-').'%@@------';
            }
            
//          excecute the tag callback
            if($this->_options['tag_global_callback'] !== false)
            {
                $tag_data = trim(call_user_func($this->_options['tag_global_callback'], 'tag', $func_name, $tag));
            }
            else
            {
                $tag_data = trim(call_user_func($func_name, $tag));
            }
            
//          this is where we sniff for buried tags within the returned content
            if(empty($tag_data) === false)
            {
                if($this->_options['sniff_for_buried_tags'] === true && strpos($tag_data, self::$tag_open.$this->_options['tag_name'].':') !== false)
                {
//                  we have the possibility of buried tags so lets parse
//                  but first make sure the output isn't echoed out
                    $old_echo_value = $this->_options['echo_output'];
                    $this->_options['echo_output'] = false; 
//                  parse the tag_data 
                    $tag_data = $this->parse($tag_data, false, true);
//                  restore the echo_output value back to what it was originally
                    $this->_options['echo_output'] = $old_echo_value;
                }
                
                if($this->_options['cache_tags'] === true && $caching_tag === true)
                {
                    if($this->_options['custom_cache_tag_class'] !== false)
                    {
                        call_user_func_array(array($this->_options['custom_cache_tag_class'], 'cache'), array($tag, $tag_data));
                    }
                    else
                    {
                        file_put_contents($this->_options['cache_directory'].md5(serialize($tag)), $tag_data, LOCK_EX);
                    }
                }
            }
            return $tag_data;
        }
307746
public function findIdentifiersByTag(string $tag): array
    {
        if (isset($this->tagsAndEntries[$tag])) {
            return array_keys($this->tagsAndEntries[$tag]);
        }
        return [];
    }
968206
public function getCreators($tag = null)
    {
        $tag = is_null($tag) ? [] : (is_array($tag) ? $tag : [$tag]);

        return array_values(array_filter(Person::get($this), function (Person $person) use ($tag) {
            return empty($tag) || in_array($person->getType(), $tag);
        }));
    }
131695
private static function parseTag($tag, $tmin, $tmax)
    {
        if ($tag == '*') {
            return range($tmin, $tmax);
        }

        $step = 1;
        $dateList = [];

        // x-x/2 情况
        if (false !== strpos($tag, ',')) {
            $tmp = explode(',', $tag);
            // 处理 xxx-xxx/x,x,x-x
            foreach ($tmp as $t) {
                if (self::checkExp($t)) {// 递归处理
                    $dateList = array_merge(self::parseTag($t, $tmin, $tmax), $dateList);
                } else {
                    $dateList[] = $t;
                }
            }
        } else if (false !== strpos($tag, '/') && false !== strpos($tag, '-')) {
            list($number, $mod) = explode('/', $tag);
            list($left, $right) = explode('-', $number);
            if ($left > $right) {
                throw new \Exception("$tag not support.");
            }
            foreach (range($left, $right) as $n) {
                if ($n % $mod === 0) {
                    $dateList[] = $n;
                }
            }
        } else if (false !== strpos($tag, '/')) {
            $tmp = explode('/', $tag);
            $step = isset($tmp[1]) ? $tmp[1] : 1;
            $dateList = range($tmin, $tmax, $step);
        } else if (false !== strpos($tag, '-')) {
            list($left, $right) = explode('-', $tag);
            if ($left > $right) {
                throw new \Exception("$tag not support.");
            }
            $dateList = range($left, $right, $step);
        } else {
            $dateList = array($tag);
        }

        // 越界判断
        foreach ($dateList as $num) {
            if ($num < $tmin || $num > $tmax) {
                throw new \Exception('Out of bounds.');
            }
        }

        sort($dateList);

        return array_unique($dateList);

    }
133113
public function _foreach($tag,$content) {
        $name       =   $tag['name'];
        $item       =   $tag['item'];
        $key        =   !empty($tag['key'])?$tag['key']:'key';
        $name       =   $this->autoBuildVar($name);
        $parseStr   =   '<?php if(is_array('.$name.')): foreach('.$name.' as $'.$key.'=>$'.$item.'): ?>';
        $parseStr  .=   $this->tpl->parse($content);
        $parseStr  .=   '<?php endforeach; endif; ?>';

        if(!empty($parseStr)) {
            return $parseStr;
        }
        return ;
    }
157964
public function _list($tag) {
        $id         = $tag['id'];                       //表格ID
        $datasource = $tag['datasource'];               //列表显示的数据源VoList名称
        $pk         = empty($tag['pk'])?'id':$tag['pk'];//主键名，默认为id
        $style      = $tag['style'];                    //样式名
        $name       = !empty($tag['name'])?$tag['name']:'vo';                 //Vo对象名
        $action     = $tag['action']=='true'?true:false;                   //是否显示功能操作
        $key         =  !empty($tag['key'])?true:false;
        $sort      = $tag['sort']=='false'?false:true;
        $checkbox   = $tag['checkbox'];                 //是否显示Checkbox
        if(isset($tag['actionlist'])) {
            if(substr($tag['actionlist'],0,1)=='$') {
                $actionlist   = $this->tpl->get(substr($tag['actionlist'],1));
            }else {
                $actionlist   = $tag['actionlist'];
            }
            $actionlist = explode(',',trim($actionlist));    //指定功能列表
        }

        if(substr($tag['show'],0,1)=='$') {
            $show   = $this->tpl->get(substr($tag['show'],1));
        }else {
            $show   = $tag['show'];
        }
        $show       = explode(',',$show);                //列表显示字段列表

        //计算表格的列数
        $colNum     = count($show);
        if(!empty($checkbox))   $colNum++;
        if(!empty($action))     $colNum++;
        if(!empty($key))  $colNum++;

        //显示开始
		$parseStr	= "<!-- Think 系统列表组件开始 -->\n";
        $parseStr  .= '<table id="'.$id.'" class="'.$style.'" cellpadding=0 cellspacing=0 >';
        $parseStr  .= '<tr><td height="5" colspan="'.$colNum.'" class="topTd" ></td></tr>';
        $parseStr  .= '<tr class="row" >';
        //列表需要显示的字段
        $fields = array();
        foreach($show as $val) {
        	$fields[] = explode(':',$val);
        }
        if(!empty($checkbox) && 'true'==strtolower($checkbox)) {//如果指定需要显示checkbox列
            $parseStr .='<th width="8"><input type="checkbox" id="check" onclick="CheckAll(\''.$id.'\')"></th>';
        }
        if(!empty($key)) {
            $parseStr .= '<th width="12">No</th>';
        }
        foreach($fields as $field) {//显示指定的字段
            $property = explode('|',$field[0]);
            $showname = explode('|',$field[1]);
            if(isset($showname[1])) {
                $parseStr .= '<th width="'.$showname[1].'">';
            }else {
                $parseStr .= '<th>';
            }
            $showname[2] = isset($showname[2])?$showname[2]:$showname[0];
            if($sort) {
                $parseStr .= '<a href="javascript:sortBy(\''.$property[0].'\',\'{$sort}\',\''.ACTION_NAME.'\')" title="按照'.$showname[2].'{$sortType} ">'.$showname[0].'<eq name="order" value="'.$property[0].'" ><img src="__PUBLIC__/images/{$sortImg}.gif" width="12" height="17" border="0" align="absmiddle"></eq></a></th>';
            }else{
                $parseStr .= $showname[0].'</th>';
            }

        }
        if(!empty($action)) {//如果指定显示操作功能列
            $parseStr .= '<th >操作</th>';
        }

        $parseStr .= '</tr>';
        $parseStr .= '<volist name="'.$datasource.'" id="'.$name.'" ><tr class="row" ';	//支持鼠标移动单元行颜色变化 具体方法在js中定义
        if(!empty($checkbox)) {
        //    $parseStr .= 'onmouseover="over(event)" onmouseout="out(event)" onclick="change(event)" ';
        }
        $parseStr .= '>';
        if(!empty($checkbox)) {//如果需要显示checkbox 则在每行开头显示checkbox
            $parseStr .= '<td><input type="checkbox" name="key"	value="{$'.$name.'.'.$pk.'}"></td>';
        }
        if(!empty($key)) {
            $parseStr .= '<td>{$i}</td>';
        }
        foreach($fields as $field) {
            //显示定义的列表字段
            $parseStr   .=  '<td>';
            if(!empty($field[2])) {
                // 支持列表字段链接功能 具体方法由JS函数实现
                $href = explode('|',$field[2]);
                if(count($href)>1) {
                    //指定链接传的字段值
                    // 支持多个字段传递
                    $array = explode('^',$href[1]);
                    if(count($array)>1) {
                        foreach ($array as $a){
                            $temp[] =  '\'{$'.$name.'.'.$a.'|addslashes}\'';
                        }
                        $parseStr .= '<a href="javascript:'.$href[0].'('.implode(',',$temp).')">';
                    }else{
                        $parseStr .= '<a href="javascript:'.$href[0].'(\'{$'.$name.'.'.$href[1].'|addslashes}\')">';
                    }
                }else {
                    //如果没有指定默认传编号值
                    $parseStr .= '<a href="javascript:'.$field[2].'(\'{$'.$name.'.'.$pk.'|addslashes}\')">';
                }
            }
            if(strpos($field[0],'^')) {
                $property = explode('^',$field[0]);
                foreach ($property as $p){
                    $unit = explode('|',$p);
                    if(count($unit)>1) {
                        $parseStr .= '{$'.$name.'.'.$unit[0].'|'.$unit[1].'} ';
                    }else {
                        $parseStr .= '{$'.$name.'.'.$p.'} ';
                    }
                }
            }else{
                $property = explode('|',$field[0]);
                if(count($property)>1) {
                    $parseStr .= '{$'.$name.'.'.$property[0].'|'.$property[1].'}';
                }else {
                    $parseStr .= '{$'.$name.'.'.$field[0].'}';
                }
            }
            if(!empty($field[2])) {
                $parseStr .= '</a>';
            }
            $parseStr .= '</td>';

        }
        if(!empty($action)) {//显示功能操作
            if(!empty($actionlist[0])) {//显示指定的功能项
                $parseStr .= '<td>';
                foreach($actionlist as $val) {
                    if(strpos($val,':')) {
                        $a = explode(':',$val);
                        if(count($a)>2) {
                            $parseStr .= '<a href="javascript:'.$a[0].'(\'{$'.$name.'.'.$a[2].'}\')">'.$a[1].'</a>&nbsp;';
                        }else {
                            $parseStr .= '<a href="javascript:'.$a[0].'(\'{$'.$name.'.'.$pk.'}\')">'.$a[1].'</a>&nbsp;';
                        }
                    }else{
                        $array	=	explode('|',$val);
                        if(count($array)>2) {
                            $parseStr	.= ' <a href="javascript:'.$array[1].'(\'{$'.$name.'.'.$array[0].'}\')">'.$array[2].'</a>&nbsp;';
                        }else{
                            $parseStr .= ' {$'.$name.'.'.$val.'}&nbsp;';
                        }
                    }
                }
                $parseStr .= '</td>';
            }
        }
        $parseStr	.= '</tr></volist><tr><td height="5" colspan="'.$colNum.'" class="bottomTd"></td></tr></table>';
        $parseStr	.= "\n<!-- Think 系统列表组件结束 -->\n";
        return $parseStr;
    }
914418
public function tagVolist($tag, $content) {
        $name = $tag['name'];
        $id = $tag['id'];
        $empty = isset($tag['empty']) ? $tag['empty'] : '';
        $key = !empty($tag['key']) ? $tag['key'] : 'i';
        $mod = isset($tag['mod']) ? $tag['mod'] : '2';
        $offset = !empty($tag['offset']) && is_numeric($tag['offset']) ? intval($tag['offset']) : 0;
        $length = !empty($tag['length']) && is_numeric($tag['length']) ? intval($tag['length']) : 'null';
        // 允许使用函数设定数据集 <volist name=":fun('arg')" id="vo">{$vo.name}</volist>
        $parseStr = '<?php ';
        $flag = substr($name, 0, 1);
        if (':' == $flag) {
            $name = $this->autoBuildVar($name);
            $parseStr .= '$_result=' . $name . ';';
            $name = '$_result';
        }
        else {
            $name = $this->autoBuildVar($name);
        }

        $parseStr .= 'if(is_array(' . $name . ') || ' . $name . ' instanceof \Traversable): $' . $key . ' = 0;';
        // 设置了输出数组长度
        if (0 != $offset || 'null' != $length) {
            $parseStr .= '$__LIST__ = is_array(' . $name . ') ? array_slice(' . $name . ',' . $offset . ',' . $length . ', true) : ' . $name . '->slice(' . $offset . ',' . $length . ', true); ';
        }
        else {
            $parseStr .= ' $__LIST__ = ' . $name . ';';
        }
        $parseStr .= 'if( count($__LIST__)==0 ) : echo "' . $empty . '" ;';
        $parseStr .= 'else: ';
        $parseStr .= 'foreach($__LIST__ as $key=>$' . $id . '): ';
        $parseStr .= '$_mod = ($' . $key . ' % ' . $mod . ' );';
        $parseStr .= '++$' . $key . ';?>';
        $parseStr .= $content;
        $parseStr .= '<?php endforeach; endif; else: echo "' . $empty . '" ;endif; ?>';

        if (!empty($parseStr)) {
            return $parseStr;
        }
        return;
    }
45810
public function getPostsByTag($tag)
    {
        if (false === array_key_exists($tag, $this->tagsIndex)) {
            return [];
        }

        $postNames = $this->tagsIndex[$tag];

        return $this->getPostsByName($postNames);
    }
474973
public static function get_tags($tags) {
        global $CFG, $PAGE, $DB;

        // Validate and normalize parameters.
        $tags = self::validate_parameters(self::get_tags_parameters(), array('tags' => $tags));

        $systemcontext = context_system::instance();
        self::validate_context($systemcontext);

        $canmanage = has_capability('moodle/tag:manage', $systemcontext);
        $canedit = has_capability('moodle/tag:edit', $systemcontext);

        $return = array();
        $warnings = array();

        if (empty($CFG->usetags)) {
            throw new moodle_exception('tagsaredisabled', 'tag');
        }

        $renderer = $PAGE->get_renderer('core');
        foreach ($tags['tags'] as $tag) {
            $tag = (array)$tag;
            if (!$tagobject = $DB->get_record('tag', array('id' => $tag['id']))) {
                $warnings[] = array(
                    'item' => $tag['id'],
                    'warningcode' => 'tagnotfound',
                    'message' => get_string('tagnotfound', 'error')
                );
                continue;
            }
            $tagoutput = new \core_tag\output\tag($tagobject);
            // Do not return some information to users without permissions.
            $rv = $tagoutput->export_for_template($renderer);
            if (!$canmanage) {
                if (!$canedit) {
                    unset($rv->isstandard);
                    unset($rv->official);
                }
                unset($rv->flag);
            }
            $return[] = $rv;
        }
        return array('tags' => $return, 'warnings' => $warnings);
    }
981781
public function search(...$tags): array
    {
        $this->validateTags($tags);
        if (!count($tags)) {
            return [];
        }
        $tags = array_unique($tags);
        $tags = array_map(function ($tag) {
            return self::PREFIX_TAG . $tag;
        }, $tags);
        $return = $this->client->evalsha(
            $this->scripts[self::SCRIPT_SEARCH],
            count($tags),
            ...$tags,
            ...[
                self::PREFIX_TAG,
                self::PREFIX_KEY_VALUE,
                self::PREFIX_KEY_TAGS,
            ]
        );
        return $return ?: [];
    }
934674
public function clearTag(string $tag): void
    {
        // 指定标签清除
        $keys = $this->getTagItems($tag);

        $this->handler->deleteMulti($keys);

        $tagName = $this->getTagKey($tag);
        $this->rm($tagName);
    }
836769
public static function getTagClassName($tag)
	{
		static $map = [
			'BARCODE' => 'BarCode',
			'BLOCKQUOTE' => 'BlockQuote',
			'COLUMN_BREAK' => 'ColumnBreak',
			'COLUMNBREAK' => 'ColumnBreak',
			'DOTTAB' => 'DotTab',
			'FIELDSET' => 'FieldSet',
			'FIGCAPTION' => 'FigCaption',
			'FORMFEED' => 'FormFeed',
			'HGROUP' => 'HGroup',
			'INDEXENTRY' => 'IndexEntry',
			'INDEXINSERT' => 'IndexInsert',
			'NEWCOLUMN' => 'NewColumn',
			'NEWPAGE' => 'NewPage',
			'PAGEFOOTER' => 'PageFooter',
			'PAGEHEADER' => 'PageHeader',
			'PAGE_BREAK' => 'PageBreak',
			'PAGEBREAK' => 'PageBreak',
			'SETHTMLPAGEFOOTER' => 'SetHtmlPageFooter',
			'SETHTMLPAGEHEADER' => 'SetHtmlPageHeader',
			'SETPAGEFOOTER' => 'SetPageFooter',
			'SETPAGEHEADER' => 'SetPageHeader',
			'TBODY' => 'TBody',
			'TFOOT' => 'TFoot',
			'THEAD' => 'THead',
			'TEXTAREA' => 'TextArea',
			'TEXTCIRCLE' => 'TextCircle',
			'TOCENTRY' => 'TocEntry',
			'TOCPAGEBREAK' => 'TocPageBreak',
			'VAR' => 'VarTag',
			'WATERMARKIMAGE' => 'WatermarkImage',
			'WATERMARKTEXT' => 'WatermarkText',
		];

		$className = 'Mpdf\Tag\\';
		$className .= isset($map[$tag]) ? $map[$tag] : ucfirst(strtolower($tag));

		return $className;
	}
196739
protected function _normalizeTag($tag) {
		$namespace = null;
		$label = $tag;
		$separator = $this->getConfig('separator');
		if ($separator === null) {
			return [
				null,
				$tag,
			];
		}

		if (strpos($tag, $separator) !== false) {
			list($namespace, $label) = explode($separator, $tag);
		}

		return [
			trim($namespace),
			trim($label)
		];
	}
750135
public function getReleaseByTagName(string $tag): array
    {
        return $this->getApi()->request($this->getApi()->sprintf('/repos/:owner/:repo/releases/tags/:tag',
            $this->getRepositories()->getOwner(), $this->getRepositories()->getRepo(), $tag));
    }