文字列に正規表現マッチをかけます。

@param	string	$pattern
@param	string	$subject
@param	array	&$matches
@param	int		$flags
@param	int		$offset
@param	string	$encoding
@return	int
554485
public static function Match ($pattern, $subject, array &$matches = array(), $flags = 0, $offset = 0, $from_encoding = Encoding::DEFAULT_ENCODING) {
		return Regex::match($pattern, $subject, $matches, $flags, $offset, $from_encoding);
	}
739266
public static function match(Token $token, array $pattern)
    {
        // Token.
        if (isset($pattern['token'])
            && ($pattern['token'] !== $token->token)
        ) {
            return false;
        }

        // Value.
        if (isset($pattern['value'])
            && ($pattern['value'] !== $token->value)
        ) {
            return false;
        }

        if (isset($pattern['value_str'])
            && strcasecmp($pattern['value_str'], (string) $token->value)
        ) {
            return false;
        }

        // Type.
        if (isset($pattern['type'])
            && ($pattern['type'] !== $token->type)
        ) {
            return false;
        }

        // Flags.
        if (isset($pattern['flags'])
            && (($pattern['flags'] & $token->flags) === 0)
        ) {
            return false;
        }

        return true;
    }
850574
public function matching ($pattern, &$matches = [], $flags = 0, $offset = 0, $start = 0, $end = null) {
		if (is_null($end)) {
			$end = $this->_length;
		}
		return static::Match($pattern, static::Substring($this->_string, $start, $end), $matches, $flags, $offset);
	}
1030103
public static function replace($pattern, $replacement, $subject, $limit = -1): ReplaceResult
    {
        return ReplaceResult::for($pattern, $replacement, $subject, $limit);
    }
821092
public function actionIndex(string $pattern): Response
    {
        /** @var Response $response */
        $response = Craft::$app->getResponse();
        $jsonOptions = null;
        $pretty = false;
        $cache = false;
        $statusCode = 200;
        $statusText = null;

        try {
            $plugin = Plugin::getInstance();
            $config = $plugin->getEndpoint($pattern);
            $request = Craft::$app->getRequest();
            $siteId = Craft::$app->getSites()->getCurrentSite()->id;

            if (is_callable($config)) {
                $params = Craft::$app->getUrlManager()->getRouteParams();
                $config = $this->_callWithParams($config, $params);
            }

            if (is_array($config)) {
                // Merge in the defaults
                $config = array_merge($plugin->getDefaultResourceAdapterConfig(), $config);
            }

            // Before anything else, check the cache
            $cache = ArrayHelper::remove($config, 'cache', false);

            if ($cache) {
                $cacheKey = 'elementapi:'.$siteId.':'.$request->getPathInfo().':'.$request->getQueryStringWithoutPath();
                $cacheService = Craft::$app->getCache();

                if (($cachedContent = $cacheService->get($cacheKey)) !== false) {
                    // Set the JSON headers
                    (new JsonResponseFormatter())->format($response);

                    // Set the cached JSON on the response and return
                    $response->format = Response::FORMAT_RAW;
                    $response->content = $cachedContent;
                    return $response;
                }
            }

            // Extract config settings that aren't meant for createResource()
            $serializer = ArrayHelper::remove($config, 'serializer');
            $jsonOptions = ArrayHelper::remove($config, 'jsonOptions', JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            $pretty = ArrayHelper::remove($config, 'pretty', false);
            $includes = ArrayHelper::remove($config, 'includes', []);
            $excludes = ArrayHelper::remove($config, 'excludes', []);

            // Generate all transforms immediately
            Craft::$app->getConfig()->getGeneral()->generateTransformsBeforePageLoad = true;

            // Get the data resource
            try {
                $resource = $plugin->createResource($config);
            } catch (\Throwable $e) {
                throw new NotFoundHttpException($e->getMessage() ?: Craft::t('element-api', 'Resource not found'), 0, $e);
            }

            // Load Fractal
            $fractal = new Manager();

            // Serialize the data
            if (!$serializer instanceof SerializerAbstract) {
                switch ($serializer) {
                    case 'dataArray':
                        $serializer = new DataArraySerializer();
                        break;
                    case 'jsonApi':
                        $serializer = new JsonApiSerializer();
                        break;
                    case 'jsonFeed':
                        $serializer = new JsonFeedV1Serializer();
                        break;
                    default:
                        $serializer = new ArraySerializer();
                }
            }

            $fractal->setSerializer($serializer);

            // Parse includes/excludes
            $fractal->parseIncludes($includes);
            $fractal->parseExcludes($excludes);

            $data = $fractal->createData($resource);

            // Fire a 'beforeSendData' event
            if ($this->hasEventHandlers(self::EVENT_BEFORE_SEND_DATA)) {
                $this->trigger(self::EVENT_BEFORE_SEND_DATA, new DataEvent([
                    'data' => $data,
                ]));
            }

            $data = $data->toArray();
        } catch (\Throwable $e) {
            $data = [
                'error' => [
                    'code' => $e instanceof HttpException ? $e->statusCode : $e->getCode(),
                    'message' => $e->getMessage(),
                ]
            ];
            $statusCode = $e instanceof HttpException ? $e->statusCode : 500;
            $statusText = $e->getMessage();
        }

        // Create a JSON response formatter with custom options
        $formatter = new JsonResponseFormatter([
            'encodeOptions' => $jsonOptions,
            'prettyPrint' => $pretty,
        ]);

        // Manually format the response ahead of time, so we can access and cache the JSON
        $response->data = $data;
        $formatter->format($response);
        $response->data = null;
        $response->format = Response::FORMAT_RAW;

        // Cache it?
        if ($cache) {
            if ($cache !== true) {
                $expire = ConfigHelper::durationInSeconds($cache);
            } else {
                $expire = null;
            }
            /** @noinspection PhpUndefinedVariableInspection */
            $cacheService->set($cacheKey, $response->content, $expire);
        }

        // Don't double-encode the data
        $response->format = Response::FORMAT_RAW;
        $response->setStatusCode($statusCode, $statusText);
        return $response;
    }
820664
private function matchesPattern($pattern) {
        $regexEncoding = mb_regex_encoding();
        mb_regex_encoding($this->encoding);

        $match = mb_ereg_match($pattern, $this->str);
        mb_regex_encoding($regexEncoding);

        return $match;
    }
1167302
public function match($pattern, $subject, &$matches = null, $flags = 0, $offset = 0)
    {
        return $this->sandbox->run('preg_match', [$pattern, $subject, &$matches, $flags, $offset], $this->throw);
    }
1159647
public function getMatchAll(string $pattern, int $flags = PREG_PATTERN_ORDER, int $offset = 0)
	{
		return preg_match_all($pattern, $this->str, $matches, $flags, $offset) === false ? null : $matches;
	}
455920
private function find($pattern, $offset = null, $normal = false)
    {
        $source = $this->source;
        $offset = ($offset === null) ? $source->cursor : $offset;
        if ($offset >= $source->bound) {
            $this->addError('The scope of the parsing template is beyond the length of the template content');
            return null;
        }
        $content = $source->substring($offset, $source->bound);
        if (!preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE)) {
            return null;
        }
        $ret = $match[0];
        $length = strlen($ret[0]);
        if ($length == 0) {
            return null;
        }
        $start = $offset + $ret[1];
        $end = $start + $length;
        if ($normal) {
            return ['val' => $ret[0], 'idx' => 0, 'start' => $start, 'end' => $end, 'len' => $length];
        }
        $match = array_filter($match, function ($item) {
            return $item[1] != -1;
        });
        foreach ($match as $k => &$v) {
            $v[2] = $k - 1;
        }
        $ret = end($match);
        return ['val' => $ret[0], 'idx' => $ret[2], 'start' => $start, 'end' => $end, 'len' => $length];
    }
1185382
public static function split($pattern, $string, $limit = -1, $flags = 0)
    {
        $offset_capture = (bool)($flags & PREG_SPLIT_OFFSET_CAPTURE);

        $lengths = self::getSplitLengths($pattern, $string);

        // Substrings
        $parts = [];
        $position = 0;
        $count = 1;
        foreach ($lengths as $length) {
            if (self::isLastPart($length, $flags, $limit, $count)) {
                $parts[] = self::makePart($string, $position, null, $offset_capture);
                return $parts;
            }

            if (self::isPart($length, $flags)) {
                $parts[] = self::makePart($string, $position, $length[0], $offset_capture);
            }

            $position += $length[0];
        }

        return $parts;
    }
1002468
public function matchQuery($pattern, &$matches = null, $flags = 0, $offset = 0)
	{
		return preg_match($pattern, $this->_query ?: '', $matches, $flags, $offset);
	}
825024
public function match(string $subject, $flags = 0, $offset = 0): int
	{
		$this->clean();
		return preg_match($this->pattern, $subject, $this->last_match, $flags, $offset);
	}
771106
public function getMatches(
        string $regex,
        int $offset = 0,
        int $flags = self::PREG_NO_FLAGS
    ): MapInterface {
        return $this->capture($regex, $offset, $flags);
    }
1033663
protected function replaceLastSequentially($search, array $replace, $subject, $encoding, &$count)
	{
		$offset = null;
		$lenSearch = mb_strlen($search, $encoding);

		foreach ($replace as $value) {
			$subject = $this->replaceLastOne($search, $value, $subject, $encoding, $count, $offset, $lenSearch);
			if($offset === false)
				break;
		}
		return $subject;
	}
261014
public static int preg_match(Pattern pattern, String subject) {
        int matches=0;
        Matcher m = pattern.matcher(subject);
        while(m.find()){ 
            ++matches;
        }
        return matches;
    }
859856
private function matches($pattern, $subject)
    {
        if (preg_match($pattern, $subject, $matches)) {
            $args = array();

            foreach ($matches as $key => $value) {
                if (!is_int($key)) {
                    $args[$key] = $value;
                }
            }

            return $args;
        }

        return false;
    }
1081855
private static function PrepareRegexPattern( $pattern, $flagString )
	{

		// Check the pattern does not include a back-reference in a character class
		$result = preg_match( "/\[.*?\\\\\d+.*?\]/", $pattern );
		if ( $result )
		{
			throw XPath2Exception::withErrorCodeAndParam( "FORX0002", Resources::InvalidRegularExpr, "$pattern/$flagString" );
		}

		// If one of the flags is x then need to remove whitespace not in character classes
		// PCRE will not remove escaped spaces when the x flag is used but XPath expects them to be removed
		if ( strpos( $flagString, "x" ) !== false )
		{
			$results = preg_match_all( "/((?<expr>[^[]*)(?<chars>\[.*?\])?)/", $pattern, $matches );
			for ( $i = 0; $i < $results; $i++ )
			{
				$match = $matches['expr'][ $i ];
				if ( empty( $match) ) continue;
				$result = preg_replace( "/((?![\r\n])\s)+/", "", $match );
				if ( $match == $result ) continue;
				$pattern = str_replace( $match, $result, $pattern );
			}
		}

		// If there is a back-reference need to add an empty comment to separate the
		// back-reference number from any following digit(s) and repeat for all back-references
		// $groups = substr_count( $pattern, "(" );
		// This pattern counts the parentheses that are not escaped by just one backslash (two is OK)
		$groups = preg_match_all( '/\\\\\\\\\(|\((?<!\\\\\()/', $pattern );
		if ( $groups )
		{
			// Get a list of all the back reference numbers
			$result = preg_match_all( "/\\\\(\d(\d?))*/", $pattern, $matches );
			if ( $result )
			{
				// $result2 = preg_match_all( "/\((([^()]+)|(?R))*\)/", $pattern, $parens );

				// Grab the valid values
				$values = array();
				foreach ( array_filter( $matches[1] ) as $key => $match )
				{
					$potentialValues = array();
					while ( strlen( $match ) > 0 )
					{
						$potentialValues[] = $match;
						$match = substr( $match, 0, strlen( $match ) - 1 );
					}

					sort( $potentialValues );
					$error = false;
					while ( count( $potentialValues ) )
					{
						$value = array_pop( $potentialValues );

						// Find the match(es) in the string and count the number of opening parentheses until that point
						$pos = strpos( $pattern, $value );

						// $matchgroupsOpen = substr_count( $pattern, "(", 0, $pos );
						// This horrible list of backslashes occurs because the regex escape char is \ and the same for PHP.
						// So every real backslash has to be quadrupled. Here's what the regex will look like outside PHP
						// 	/\\\\\(|\((?<!\\\()/
						$matchgroupsOpen = preg_match_all( '/\\\\\\\\\(|\((?<!\\\\\()/', substr( $pattern, 0, $pos ) );

						// If there are no groups throw an exception
						$error = ! $matchgroupsOpen || $matchgroupsOpen < $value;

						if ( ! $error )
						{
							// $matchgroupsClosed = substr_count( $pattern, ")", 0, $pos );
							$matchgroupsClosed = preg_match_all( '/\\\\\\\\\)|\)(?<!\\\\\))/', substr( $pattern, 0, $pos ) );

							// If reference is in a capture group its an error
							$error = ! $matchgroupsClosed || $matchgroupsClosed != $matchgroupsOpen || $matchgroupsClosed < $value;

							if ( $error ) continue;
							// This is the longest number
							$values[] = $value;
							break;
						}
					}

					if ( $error )
					{
						throw XPath2Exception::withErrorCode( "FORX0002", Resources::FORX0002 );
					}
				}

				// Make sure the back-reference numbers are valid given the list of capture groups available
				$validValues = array_intersect( $values, range( 1, $groups ) );

				// Sort them in descending order so the longest number is handled first.
				// This way \1 and \11 are handled correctly.
				// BMS Not sure this is necessary.
				rsort( $validValues );
				foreach ( $validValues as $value )
				{
					// Replace the number but only if the number is not already followed by an empty comment
					$pattern = preg_replace( "/\\\\($value)(?!\d?\(\?\#\))/", "\\\\$1(?#)", $pattern );
				}
			}
		}

		// Check to see if there are any character classes that specify character subtraction
		// If so, convert to a negative lookahead
		$results = preg_match_all( "/\[(?<chars>((.*)?(.-.))+)-(?<sub>\[(.*|.*?(.-.))+\])\]/", $pattern, $matches );
		if ( $results )
		{
			for ( $i = 0; $i < $results; $i++ )
			{
				$chars = $matches['chars'][ $i ];
				$sub = $matches['sub'][ $i ];
				$x = "(?!$sub)[$chars]";

				$pattern = str_replace( $matches[ $i ], $x, $pattern );
			}
		}

		// Replace common unicode character classes
		$pattern = str_replace( "{IsBasic", "{", $pattern );

		return $pattern;
	}