*
* @author Fabien Potencier <fabien@symfony.com>
*
* @see https://twig.symfony.com/doc/templates.html#functions
*/
class TwigFunction
{
private $name;
private $callable;
private $options;
private $arguments = [];
/**
* Creates a template function.
*
* @param string $name Name of this function
* @param callable|null $callable A callable implementing the function. If null, you need to overwrite the "node_class" option to customize compilation.
* @param array $options Options array
*/
public function __construct(string $name, $callable = null, array $options = [])
{
if (__CLASS__ !== static::class) {
@trigger_error('Overriding '.__CLASS__.' is deprecated since Twig 2.4.0 and the class will be final in 3.0.', \E_USER_DEPRECATED);
}
$this->name = $name;
$this->callable = $callable;
$this->options = array_merge([
'needs_environment' => false,
'needs_context' => false,
'is_variadic' => false,
'is_safe' => null,
'is_safe_callback' => null,
'node_class' => FunctionExpression::class,
'deprecated' => false,
'alternative' => null,
], $options);
}
public function getName()
*/
/**
* Represents a method template function.
*
* Use Twig_SimpleFunction instead.
*
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
class Twig_Function_Method extends Twig_Function
{
protected $extension;
protected $method;
public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
{
$options['callable'] = array($extension, $method);
parent::__construct($options);
$this->extension = $extension;
$this->method = $method;
}
public function compile()
{
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
}
}
/**
* @var Ai1ec_Registry_Object
*/
protected $_registry;
/**
* Inject the registry object.
*
* @param Ai1ec_Registry_Object $registry
*/
public function set_registry( Ai1ec_Registry_Object $registry ) {
$this->_registry = $registry;
}
/* (non-PHPdoc)
* @see Twig_Extension::getFunctions()
*/
public function getFunctions() {
return array(
'wp_nonce_field' => new Twig_Function_Method( $this, 'wp_nonce_field' ),
'do_meta_boxes' => new Twig_Function_Method( $this, 'do_meta_boxes' ),
'fb' => new Twig_Function_Method( $this, 'fb' ),
'ai1ec_disable_content_output' => new Twig_Function_Method( $this, 'ai1ec_disable_content_output' )
);
}
/**
* Twig callback - return a list of filters registered by this extension.
*
* @return array
*/
public function getFilters() {
return array(
new Twig_SimpleFilter( 'truncate', array( $this, 'truncate' ) ),
new Twig_SimpleFilter( 'timespan', array( $this, 'timespan' ) ),
new Twig_SimpleFilter( 'avatar', array( $this, 'avatar' ) ),
new Twig_SimpleFilter( 'avatar_url', array( $this, 'avatar_url' ) ),
new Twig_SimpleFilter( 'remove_avatar_url', array( $this, 'remove_avatar_url' ) ),
new Twig_SimpleFilter( 'remove_paragraph', array( $this, 'remove_paragraph' ) ),
new Twig_SimpleFilter( 'hour_to_datetime', array( $this, 'hour_to_datetime' ) ),
$this->unaryOperators = [];
$this->binaryOperators = [];
foreach ($this->extensions as $extension) {
$this->initExtension($extension);
}
$this->initExtension($this->staging);
// Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception
$this->initialized = true;
}
private function initExtension(ExtensionInterface $extension)
{
// filters
foreach ($extension->getFilters() as $filter) {
$this->filters[$filter->getName()] = $filter;
}
// functions
foreach ($extension->getFunctions() as $function) {
$this->functions[$function->getName()] = $function;
}
// tests
foreach ($extension->getTests() as $test) {
$this->tests[$test->getName()] = $test;
}
// token parsers
foreach ($extension->getTokenParsers() as $parser) {
if (!$parser instanceof TokenParserInterface) {
throw new \LogicException('getTokenParsers() must return an array of \Twig\TokenParser\TokenParserInterface.');
}
$this->parsers[] = $parser;
}
// node visitors
foreach ($extension->getNodeVisitors() as $visitor) {
$this->visitors[] = $visitor;
{
if (!$this->initialized) {
$this->initExtensions();
}
return $this->binaryOperators;
}
private function initExtensions()
{
$this->parsers = [];
$this->filters = [];
$this->functions = [];
$this->tests = [];
$this->visitors = [];
$this->unaryOperators = [];
$this->binaryOperators = [];
foreach ($this->extensions as $extension) {
$this->initExtension($extension);
}
$this->initExtension($this->staging);
// Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception
$this->initialized = true;
}
private function initExtension(ExtensionInterface $extension)
{
// filters
foreach ($extension->getFilters() as $filter) {
$this->filters[$filter->getName()] = $filter;
}
// functions
foreach ($extension->getFunctions() as $function) {
$this->functions[$function->getName()] = $function;
}
// tests
foreach ($extension->getTests() as $test) {
foreach ($this->tests as $pattern => $test) {
$pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
if ($count) {
if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
array_shift($matches);
$test->setArguments($matches);
return $test;
}
}
}
return false;
}
public function getUnaryOperators(): array
{
if (!$this->initialized) {
$this->initExtensions();
}
return $this->unaryOperators;
}
public function getBinaryOperators(): array
{
if (!$this->initialized) {
$this->initExtensions();
}
return $this->binaryOperators;
}
private function initExtensions()
{
$this->parsers = [];
$this->filters = [];
$this->functions = [];
$this->tests = [];
// bigger than globals, this code is faster.
foreach ($this->getGlobals() as $key => $value) {
if (!\array_key_exists($key, $context)) {
$context[$key] = $value;
}
}
return $context;
}
/**
* Gets the registered unary Operators.
*
* @return array An array of unary operators
*
* @internal
*/
public function getUnaryOperators()
{
return $this->extensionSet->getUnaryOperators();
}
/**
* Gets the registered binary Operators.
*
* @return array An array of binary operators
*
* @internal
*/
public function getBinaryOperators()
{
return $this->extensionSet->getBinaryOperators();
}
private function updateOptionsHash()
{
$this->optionsHash = implode(':', [
$this->extensionSet->getSignature(),
\PHP_MAJOR_VERSION,
\PHP_MINOR_VERSION,
{
// do not push empty text tokens
if (/* Token::TEXT_TYPE */ 0 === $type && '' === $value) {
return;
}
$this->tokens[] = new Token($type, $value, $this->lineno);
}
private function moveCursor($text)
{
$this->cursor += \strlen($text);
$this->lineno += substr_count($text, "\n");
}
private function getOperatorRegex()
{
$operators = array_merge(
['='],
array_keys($this->env->getUnaryOperators()),
array_keys($this->env->getBinaryOperators())
);
$operators = array_combine($operators, array_map('strlen', $operators));
arsort($operators);
$regex = [];
foreach ($operators as $operator => $length) {
// an operator that ends with a character must be followed by
// a whitespace, a parenthesis, an opening map [ or sequence {
$r = preg_quote($operator, '/');
if (ctype_alpha($operator[$length - 1])) {
$r .= '(?=[\s()\[{])';
}
// an operator that begins with a character must not have a dot or pipe before
if (ctype_alpha($operator[0])) {
$r = '(?<![\.\|])'.$r;
}
}Ax',
// {% endverbatim %}
'lex_raw_data' => '{'.
preg_quote($this->options['tag_block'][0], '#'). // {%
'('.
$this->options['whitespace_trim']. // -
'|'.
$this->options['whitespace_line_trim']. // ~
')?\s*endverbatim\s*'.
'(?:'.
preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%}
'|'.
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]*
'|'.
preg_quote($this->options['tag_block'][1], '#'). // %}
')
}sx',
'operator' => $this->getOperatorRegex(),
// #}
'lex_comment' => '{
(?:'.
preg_quote($this->options['whitespace_trim'].$this->options['tag_comment'][1], '#').'\s*\n?'. // -#}\s*\n?
'|'.
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_comment'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~#}[ \t\0\x0B]*
'|'.
preg_quote($this->options['tag_comment'][1], '#').'\n?'. // #}\n?
')
}sx',
// verbatim %}
'lex_block_raw' => '{
\s*verbatim\s*
(?:'.
preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%}\s*
'|'.
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]*
'|'.
('.
preg_quote($this->options['tag_variable'][0], '#'). // {{
'|'.
preg_quote($this->options['tag_block'][0], '#'). // {%
'|'.
preg_quote($this->options['tag_comment'][0], '#'). // {#
')('.
preg_quote($this->options['whitespace_trim'], '#'). // -
'|'.
preg_quote($this->options['whitespace_line_trim'], '#'). // ~
')?
}sx',
'interpolation_start' => '{'.preg_quote($this->options['interpolation'][0], '#').'\s*}A',
'interpolation_end' => '{\s*'.preg_quote($this->options['interpolation'][1], '#').'}A',
];
}
public function tokenize(Source $source)
{
$this->initialize();
$this->source = $source;
$this->code = str_replace(["\r\n", "\r"], "\n", $source->getCode());
$this->cursor = 0;
$this->lineno = 1;
$this->end = \strlen($this->code);
$this->tokens = [];
$this->state = self::STATE_DATA;
$this->states = [];
$this->brackets = [];
$this->position = -1;
// find all token starts in one go
preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, \PREG_OFFSET_CAPTURE);
$this->positions = $matches;
while ($this->cursor < $this->end) {
// dispatch to the lexing functions depending
// on the current state
switch ($this->state) {
public function setLexer(Lexer $lexer)
{
$this->lexer = $lexer;
}
/**
* Tokenizes a source code.
*
* @return TokenStream
*
* @throws SyntaxError When the code is syntactically wrong
*/
public function tokenize(Source $source)
{
if (null === $this->lexer) {
$this->lexer = new Lexer($this);
}
return $this->lexer->tokenize($source);
}
public function setParser(Parser $parser)
{
$this->parser = $parser;
}
/**
* Converts a token stream to a node tree.
*
* @return ModuleNode
*
* @throws SyntaxError When the token stream is syntactically or semantically wrong
*/
public function parse(TokenStream $stream)
{
if (null === $this->parser) {
$this->parser = new Parser($this);
}
public function compile(Node $node)
{
if (null === $this->compiler) {
$this->compiler = new Compiler($this);
}
return $this->compiler->compile($node)->getSource();
}
/**
* Compiles a template source code.
*
* @return string The compiled PHP source code
*
* @throws SyntaxError When there was an error during tokenizing, parsing or compiling
*/
public function compileSource(Source $source)
{
try {
return $this->compile($this->parse($this->tokenize($source)));
} catch (Error $e) {
$e->setSourceContext($source);
throw $e;
} catch (\Exception $e) {
throw new SyntaxError(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e);
}
}
public function setLoader(LoaderInterface $loader)
{
$this->loader = $loader;
}
/**
* Gets the Loader instance.
*
* @return LoaderInterface
*/
public function getLoader()
{
$mainCls = $cls;
if (null !== $index) {
$cls .= '___'.$index;
}
if (isset($this->loadedTemplates[$cls])) {
return $this->loadedTemplates[$cls];
}
if (!class_exists($cls, false)) {
$key = $this->cache->generateKey($name, $mainCls);
if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) {
$this->cache->load($key);
}
$source = null;
if (!class_exists($cls, false)) {
$source = $this->getLoader()->getSourceContext($name);
$content = $this->compileSource($source);
$this->cache->write($key, $content);
$this->cache->load($key);
if (!class_exists($mainCls, false)) {
/* Last line of defense if either $this->bcWriteCacheFile was used,
* $this->cache is implemented as a no-op or we have a race condition
* where the cache was cleared between the above calls to write to and load from
* the cache.
*/
eval('?>'.$content);
}
if (!class_exists($cls, false)) {
throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source);
}
}
}
// to be removed in 3.0
$this->extensionSet->initRuntime($this);
/**
* Loads a template internal representation.
*
* This method is for internal use only and should never be called
* directly.
*
* @param string $name The template name
* @param int $index The index if it is an embedded template
*
* @return Template A template instance representing the given template name
*
* @throws LoaderError When the template cannot be found
* @throws RuntimeError When a previously generated cache is corrupted
* @throws SyntaxError When an error occurred during compilation
*
* @internal
*/
public function loadTemplate($name, $index = null)
{
return $this->loadClass($this->getTemplateClass($name), $name, $index);
}
/**
* @internal
*/
public function loadClass($cls, $name, $index = null)
{
$mainCls = $cls;
if (null !== $index) {
$cls .= '___'.$index;
}
if (isset($this->loadedTemplates[$cls])) {
return $this->loadedTemplates[$cls];
}
if (!class_exists($cls, false)) {
$key = $this->cache->generateKey($name, $mainCls);
if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) {
* @subpackage AI1EC.Twig
*/
class Ai1ec_Twig_Environment extends Twig_Environment {
/**
* @var Ai1ec_Registry_Object The registry Object.
*/
protected $_registry = null;
/**
* Loads a template by name.
*
* @param string $name The template name
* @param integer $index The index if it is an embedded template
*
* @return Twig_TemplateInterface A template instance representing the given template name
*/
public function loadTemplate( $name, $index = null ) {
try {
return parent::loadTemplate( $name, $index );
} catch ( RuntimeException $excpt ) {
/*
* We should not rely on is_writable - WP Engine case.
* I've made twig directory read-only and is_writable was returning
* true.
*/
$this->_registry->get(
'twig.cache'
)->set_unavailable( $this->cache );
/*
* Some copy paste from original Twig method. Just to avoid first
* error during rendering.
*/
$cls = $this->getTemplateClass( $name, $index );
eval(
'?>' .
$this->compileSource(
$this->getLoader()->getSource( $name ),
$name
)
*
* @throws LoaderError When the template cannot be found
* @throws RuntimeError When a previously generated cache is corrupted
* @throws SyntaxError When an error occurred during compilation
*
* @return TemplateWrapper
*/
public function load($name)
{
if ($name instanceof TemplateWrapper) {
return $name;
}
if ($name instanceof Template) {
@trigger_error('Passing a \Twig\Template instance to '.__METHOD__.' is deprecated since Twig 2.7.0, use \Twig\TemplateWrapper instead.', \E_USER_DEPRECATED);
return new TemplateWrapper($this, $name);
}
return new TemplateWrapper($this, $this->loadTemplate($name));
}
/**
* Loads a template internal representation.
*
* This method is for internal use only and should never be called
* directly.
*
* @param string $name The template name
* @param int $index The index if it is an embedded template
*
* @return Template A template instance representing the given template name
*
* @throws LoaderError When the template cannot be found
* @throws RuntimeError When a previously generated cache is corrupted
* @throws SyntaxError When an error occurred during compilation
*
* @internal
*/
public function loadTemplate($name, $index = null)
$key = $this->getLoader()->getCacheKey($name).$this->optionsHash;
return $this->templateClassPrefix.hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $key).(null === $index ? '' : '___'.$index);
}
/**
* Renders a template.
*
* @param string|TemplateWrapper $name The template name
* @param array $context An array of parameters to pass to the template
*
* @return string The rendered template
*
* @throws LoaderError When the template cannot be found
* @throws SyntaxError When an error occurred during compilation
* @throws RuntimeError When an error occurred during rendering
*/
public function render($name, array $context = [])
{
return $this->load($name)->render($context);
}
/**
* Displays a template.
*
* @param string|TemplateWrapper $name The template name
* @param array $context An array of parameters to pass to the template
*
* @throws LoaderError When the template cannot be found
* @throws SyntaxError When an error occurred during compilation
* @throws RuntimeError When an error occurred during rendering
*/
public function display($name, array $context = [])
{
$this->load($name)->display($context);
}
/**
* Loads a template.
*
*/
public function set_registry( Ai1ec_Registry_Object $registry ) {
$this->_registry = $registry;
}
/**
* Renders a template.
*
* @param string $name The template name
* @param array $context An array of parameters to pass to the template
*
* @return string The rendered template
*
* @throws Twig_Error_Loader When the template cannot be found
* @throws Twig_Error_Syntax When an error occurred during compilation
* @throws Twig_Error_Runtime When an error occurred during rendering
*/
public function render( $name, array $context = array() ) {
try {
return parent::render( $name, $context );
} catch ( Exception $excpt ) {
if (
! defined( 'AI1EC_DEBUG' ) ||
! AI1EC_DEBUG
) {
return $this->_handle_render_exception( $name, $context );
}
throw $excpt;
}
}
/**
* Switches calendar theme to vortex.
*
* @return void Method does not return.
*
* @throws Ai1ec_Bootstrap_Exception
*/
public function switch_to_vortex() {
$this->_registry->get( 'theme.loader' )->switch_to_vortex();
}
/**
* Adds the given search path to the front of the list (high priority).
*
* @param string $search_path Path to add to front of list
*/
public function prepend_path( $search_path ) {
$loader = $this->_twig->getLoader();
$loader->prependPath( $search_path );
}
/* (non-PHPdoc)
* @see Ai1ec_File::locate_file()
*/
public function process_file() {
$loader = $this->_twig->getLoader();
if ( $loader->exists( $this->_name ) ) {
$this->_content = $this->_twig->render( $this->_name, $this->_args );
return true;
}
return false;
}
}
'theme.file.twig',
$filename,
$args,
$this->_get_twig_instance( $paths, $is_admin )
);
}
break;
default:
throw new Ai1ec_Exception(
sprintf(
Ai1ec_I18n::__( "We couldn't find a suitable loader for filename with extension '%s'" ),
$ext
)
);
break;
}
// here file is a concrete class otherwise the exception is thrown
if ( ! $file->process_file() && true === $throw_exception ) {
throw new Ai1ec_Exception(
'The specified file "' . $filename . '" doesn\'t exist.'
);
}
return $file;
}
/**
* Reuturns loader paths.
*
* @return array Loader paths.
*/
public function get_paths() {
return $this->_paths;
}
/**
* Tries to load a PHP file from the theme. If not present, it falls back to
* Twig.
*
$text_calendar_feed = Ai1ec_I18n::__(
'This post was replicated from another site\'s <a href="%s" title="iCalendar feed"><i class="ai1ec-fa ai1ec-fa-calendar"></i> calendar feed</a>.'
);
} else {
$text_calendar_feed = Ai1ec_I18n::__(
'This post was imported from a CSV/ICS file.'
);
}
$loader = $this->_registry->get( 'theme.loader' );
$text_calendar_feed = sprintf(
$text_calendar_feed,
esc_attr( str_replace( 'http://', 'webcal://', $event->get( 'ical_feed_url' ) ) )
);
$args = array(
'event' => $event,
'text_calendar_feed' => $text_calendar_feed,
'text_view_post' => Ai1ec_I18n::__( 'View original' ),
);
return $loader->get_file( 'event-single-footer.twig', $args, false )
->get_content();
}
/**
* Render the full article for the event – title, content, and footer.
*
* @param Ai1ec_Event $event
* @param string $footer Footer HTML to append to event
*/
public function get_full_article( Ai1ec_Event $event, $footer = '' ) {
$title = apply_filters(
'the_title',
$event->get( 'post' )->post_title,
$event->get( 'post_id' )
);
$event_details = $this->get_content( $event );
$content = wpautop(
apply_filters(
'ai1ec_the_content',
apply_filters(
// If not on the single event page, return nothing.
if ( ! is_single() ) {
return array(
'data' => '',
'is_event' => true,
);
}
// Else proceed with rendering valid event. Fetch all relevant details.
$instance = -1;
if ( isset( $_REQUEST['instance_id'] ) ) {
$instance = (int)$_REQUEST['instance_id'];
}
$event = $this->_registry->get(
'model.event',
get_the_ID(),
$instance
);
$event_page = $this->_registry->get( 'view.event.single' );
$footer_html = $event_page->get_footer( $event );
$css = $this->_registry->get( 'css.frontend' )
->add_link_to_html_for_frontend();
$js = $this->_registry->get( 'controller.javascript' )
->load_frontend_js( false );
// If requesting event by JSON (remotely), return fully rendered event.
if ( 'html' !== $this->_request_type ) {
return array(
'data' => array(
'html' => $event_page->get_full_article( $event, $footer_html )
),
'callback' => Ai1ec_Request_Parser::get_param( 'callback', null ),
);
}
// Else return event details as components.
return array(
'data' => $event_page->get_content( $event ),
'is_event' => true,
'footer' => $footer_html,
);
) {
return array(
'controller' => $controller,
'action' => $action
);
}
return false;
}
/**
* Execute the command.
*
* @return void
*/
public function execute() {
// Set the render strategy
$this->set_render_strategy( $this->_request );
// get the data from the concrete implementation
$data = $this->do_execute();
// render it.
$this->_render_strategy->render( $data );
}
/**
* Defines whether to stop execution of command loop or not.
*
* @return bool True or false.
*/
public function stop_execution() {
return false;
}
/**
* The abstract method concrete command must implement.
*
* Retrieve whats needed and returns it
*
* @return array
*/
/**
* Execute commands if our plugin must handle the request.
*
* @wp_hook init
*
* @return void
*/
public function route_request() {
$this->_process_request();
// get the resolver
$resolver = $this->_registry->get(
'command.resolver',
$this->_request
);
// get the command
$commands = $resolver->get_commands();
// if we have a command
if ( ! empty( $commands ) ) {
foreach( $commands as $command ) {
$result = $command->execute();
if ( $command->stop_execution() ) {
return $result;
}
}
}
}
/**
* Initializes the URL router used by our plugin.
*
* @wp_hook init
*
* @return void
*/
public function initialize_router() {
/* @var $cal_state Ai1ec_Calendar_State */
$cal_state = $this->_registry->get( 'calendar.state' );
$cal_state->set_routing_initialization( true );
$settings = $this->_registry->get( 'model.settings' );
$cal_page = $settings->get( 'calendar_page_id' );
$this->iterations[ $nesting_level ] = $this->priorities;
$num_args = count( $args );
do {
$this->current_priority[ $nesting_level ] = current( $this->iterations[ $nesting_level ] );
$priority = $this->current_priority[ $nesting_level ];
foreach ( $this->callbacks[ $priority ] as $the_ ) {
if ( ! $this->doing_action ) {
$args[0] = $value;
}
// Avoid the array_slice() if possible.
if ( 0 === $the_['accepted_args'] ) {
$value = call_user_func( $the_['function'] );
} elseif ( $the_['accepted_args'] >= $num_args ) {
$value = call_user_func_array( $the_['function'], $args );
} else {
$value = call_user_func_array( $the_['function'], array_slice( $args, 0, $the_['accepted_args'] ) );
}
}
} while ( false !== next( $this->iterations[ $nesting_level ] ) );
unset( $this->iterations[ $nesting_level ] );
unset( $this->current_priority[ $nesting_level ] );
--$this->nesting_level;
return $value;
}
/**
* Calls the callback functions that have been added to an action hook.
*
* @since 4.7.0
*
* @param array $args Parameters to pass to the callback functions.
} while ( false !== next( $this->iterations[ $nesting_level ] ) );
unset( $this->iterations[ $nesting_level ] );
unset( $this->current_priority[ $nesting_level ] );
--$this->nesting_level;
return $value;
}
/**
* Calls the callback functions that have been added to an action hook.
*
* @since 4.7.0
*
* @param array $args Parameters to pass to the callback functions.
*/
public function do_action( $args ) {
$this->doing_action = true;
$this->apply_filters( '', $args );
// If there are recursive calls to the current action, we haven't finished it until we get to the last one.
if ( ! $this->nesting_level ) {
$this->doing_action = false;
}
}
/**
* Processes the functions hooked into the 'all' hook.
*
* @since 4.7.0
*
* @param array $args Arguments to pass to the hook callbacks. Passed by reference.
*/
public function do_all_hook( &$args ) {
$nesting_level = $this->nesting_level++;
$this->iterations[ $nesting_level ] = $this->priorities;
do {
$priority = current( $this->iterations[ $nesting_level ] );
if ( ! isset( $wp_filter[ $hook_name ] ) ) {
if ( isset( $wp_filter['all'] ) ) {
array_pop( $wp_current_filter );
}
return;
}
if ( ! isset( $wp_filter['all'] ) ) {
$wp_current_filter[] = $hook_name;
}
if ( empty( $arg ) ) {
$arg[] = '';
} elseif ( is_array( $arg[0] ) && 1 === count( $arg[0] ) && isset( $arg[0][0] ) && is_object( $arg[0][0] ) ) {
// Backward compatibility for PHP4-style passing of `array( &$this )` as action `$arg`.
$arg[0] = $arg[0][0];
}
$wp_filter[ $hook_name ]->do_action( $arg );
array_pop( $wp_current_filter );
}
/**
* Calls the callback functions that have been added to an action hook, specifying arguments in an array.
*
* @since 2.1.0
*
* @see do_action() This function is identical, but the arguments passed to the
* functions hooked to `$hook_name` are supplied using an array.
*
* @global WP_Hook[] $wp_filter Stores all of the filters and actions.
* @global int[] $wp_actions Stores the number of times each action was triggered.
* @global string[] $wp_current_filter Stores the list of current filters with the current one last.
*
* @param string $hook_name The name of the action to be executed.
* @param array $args The arguments supplied to the functions hooked to `$hook_name`.
*/
function do_action_ref_array( $hook_name, $args ) {
*
* @package WordPress
*/
if ( wp_using_themes() ) {
/**
* Fires before determining which template to load.
*
* This action hook executes just before WordPress determines which template page to load.
* It is a good hook to use if you need to do a redirect with full knowledge of the content
* that has been queried.
*
* Note: Loading a different template is not a good use of this hook. If you include another template
* and then use `exit()` or `die()`, no subsequent `template_redirect` hooks will be run, which could
* break the site’s functionality. Instead, use the {@see 'template_include'} filter hook to return
* the path to the new template you want to use. This will allow an alternative template to be used
* without interfering with the WordPress loading process.
*
* @since 1.5.0
*/
do_action( 'template_redirect' );
}
/**
* Filters whether to allow 'HEAD' requests to generate content.
*
* Provides a significant performance bump by exiting before the page
* content loads for 'HEAD' requests. See #14348.
*
* @since 3.5.0
*
* @param bool $exit Whether to exit without generating any content for 'HEAD' requests. Default true.
*/
if ( 'HEAD' === $_SERVER['REQUEST_METHOD'] && apply_filters( 'exit_on_http_head', true ) ) {
exit;
}
// Process feeds and trackbacks even if not using themes.
if ( is_robots() ) {
/**
* Fired when the template loader determines a robots.txt request.
<?php
/**
* Loads the WordPress environment and template.
*
* @package WordPress
*/
if ( ! isset( $wp_did_header ) ) {
$wp_did_header = true;
// Load the WordPress library.
require_once __DIR__ . '/wp-load.php';
// Set up the WordPress query.
wp();
// Load the theme template.
require_once ABSPATH . WPINC . '/template-loader.php';
}
<?php
/**
* Front to the WordPress application. This file doesn't do anything, but loads
* wp-blog-header.php which does and tells WordPress to load the theme.
*
* @package WordPress
*/
/**
* Tells WordPress to load the WordPress theme and output it.
*
* @var bool
*/
define( 'WP_USE_THEMES', true );
/** Loads the WordPress Environment and Template */
require __DIR__ . '/wp-blog-header.php';