/** * All handlers must implement act() to conform to handler API. * This is the default implementation of act(), which attempts * to call a class member method of $this->act_$action(). Any * subclass is welcome to override this default implementation. * * @param string $action the action that was in the URL rule */ public function act($action) { if (null === $this->handler_vars) { $this->handler_vars = new SuperGlobal(array()); } $this->action = $action; $this->theme->assign('matched_rule', URL::get_matched_rule()); $request = new StdClass(); foreach (URL::get_active_rules() as $rule) { $request->{$rule->name} = false; } $request->{$this->theme->matched_rule->name} = true; $this->theme->assign('request', $request); $action_hook = 'plugin_act_' . $action; $before_action_hook = 'before_' . $action_hook; $theme_hook = 'route_' . $action; $after_action_hook = 'after_' . $action_hook; Plugins::act($before_action_hook, $this); Plugins::act($action_hook, $this); if (Plugins::implemented($theme_hook, 'theme')) { $theme = Themes::create(); $rule = URL::get_matched_rule(); Plugins::theme($theme_hook, $theme, $rule->named_arg_values, $this); } Plugins::act($after_action_hook); }
/** * function __set * Handles setting virtual properties for this class * @param string Name of the property * @param mixed Value to set it to * @return mixed The set value **/ public function __set($name, $value) { $classname = strtolower(get_class($this)); $hook = 'set_' . $classname . '_' . $name; if (Plugins::implemented($hook, 'action')) { return Plugins::act('set_' . $classname . '_' . $name, $value, $this); } if (isset($this->properties_loaded[$name])) { $this->newfields[$name] = $value; } else { $this->fields[$name] = $value; $this->properties_loaded[$name] = true; } return $value; }
/** * Overrides QueryRecord __get to implement custom object properties * @param string $name Name of property to return * @return mixed The requested field value */ public function __get($name) { // some properties are considered special and accidentally filtering them would be bad, so we exclude those $fieldnames = array_merge(array_keys($this->fields), array('permalink', 'tags', 'comments', 'comment_count', 'approved_comment_count', 'comment_feed_link', 'author', 'editlink', 'info')); $filter = false; if (!in_array($name, $fieldnames) && strpos($name, '_') !== false) { $field_matches = implode('|', $fieldnames); if (preg_match('/^(' . $field_matches . ')_(.+)$/', $name, $matches)) { list($junk, $name, $filter) = $matches; } } switch ($name) { case 'statusname': $out = self::status_name($this->status); break; case 'typename': $out = self::type_name($this->content_type); break; case 'permalink': $out = $this->get_permalink(); break; case 'editlink': $out = $this->get_editlink(); break; case 'tags': $out = $this->get_tags(); break; case 'comments': $out = $this->get_comments(); break; case 'comment_count': $out = $this->get_comments()->count(); break; case 'approved_comment_count': $out = Comments::count_by_id($this->id); break; case 'comment_feed_link': $out = $this->get_comment_feed_link(); break; case 'author': $out = $this->get_author(); break; case 'info': $out = $this->get_info(); break; case 'excerpt': $field = 'content' . ($filter ? '_' . $filter : '_out'); $out = $this->__get($field); if (!Plugins::implemented('post_excerpt', 'filter')) { $out = Format::more($out, $this, Options::get('excerpt_settings', array('max_paragraphs' => 2))); } break; default: $out = parent::__get($name); break; } if ($filter != 'internal') { $out = Plugins::filter("post_get", $out, $name, $this); $out = Plugins::filter("post_{$name}", $out, $this); } if ($filter) { $out = Plugins::filter("post_{$name}_{$filter}", $out, $this); } return $out; }
/** * Runs this job. * * Executes the Cron Job callback. Deletes the Cron Job if end_time is reached * or if it failed to execute the last # consecutive attempts. Also sends notification * by email to specified address. * Note: end_time can be null, ie. "The Never Ending Cron Job". * * Callback is passed a param_array of the Cron Job fields and the execution time * as the 'now' field. The 'result' field contains the result of the last execution; either * 'executed' or 'failed'. * * @todo send notification of execution/failure. */ public function execute() { $paramarray = array_merge(array('now' => $this->now), $this->to_array()); // this is an ugly hack that we could probably work around better by forking each cron into its own process // we increment the failure count now so that if we don't return after calling the callback (ie: a fatal error) it still counts against it, rather than simply never running // and preventing all those queued up after it from running $this->failures = $this->failures + 1; // check to see if we have failed too many times before we update, we might go ahead and skip this one if ($this->failures > Options::get('cron_max_failures', 10)) { EventLog::log(_t('CronJob %s has failed %d times and is being deactivated!', array($this->name, $this->failures - 1)), 'alert', 'cron'); $this->active = 0; } // update before we run it $this->update(); // if the check has been deactivated, just return if ($this->active == 0) { return; } if (is_callable($this->callback)) { // this is a callable we can actually call, so do it $result = call_user_func($this->callback, $paramarray); } else { if (!is_string($this->callback) && is_callable($this->callback, true, $callable_name)) { // this looks like a callable to PHP, but it cannot be called at present and should not be assumed to be a plugin filter name // there is nothing for us to do, but it was a specifically-named function for us to call, so assume this is a failure $result = false; } else { // this is not callable and doesn't look like one - it should simply be a textual plugin filter name // is this plugin filter actually implemented? if (Plugins::implemented($this->callback, 'filter')) { // then run it and use that result $result = true; $result = Plugins::filter($this->callback, $result, $paramarray); } else { // the filter isn't implemented, consider that a failure $result = false; } } } if ($result === false) { $this->result = 'failed'; // simply increment the failure counter. if it's over the limit it'll be deactivated on the next go-around $this->failures = $this->failures + 1; EventLog::log(_t('CronJob %s failed.', array($this->name)), 'err', 'cron'); } else { $this->result = 'executed'; // reset failures, we were successful $this->failures = 0; EventLog::log(_t('CronJob %s completed successfully.', array($this->name)), 'debug', 'cron'); // it ran successfully, so check if it's time to delete it. if (!is_null($this->end_time) && $this->now >= $this->end_time) { EventLog::log(_t('CronJob %s is not scheduled to run again and is being deleted.', array($this->name)), 'debug', 'cron'); $this->delete(); return; } } $this->last_run = $this->now; $this->next_run = $this->now->int + $this->increment; $this->update(); }