/** * Execute the actual cron for the requested type. * * @param string $cron Cron type to execute. * * @return CronLogModel * @throws Exception */ private function _performcron($cron) { switch ($cron) { case '1-minute': case '5-minute': case '15-minute': case '30-minute': case 'hourly': case '2-hour': case '3-hour': case '6-hour': case '12-hour': case 'daily': case 'weekly': case 'monthly': break; default: throw new Exception('Unsupported cron type: [' . $cron . ']'); } if (!ConfigHandler::Get('/cron/enabled')) { $msg = 'Cron execution is globally disabled via the site configuration, not executing cron!'; SystemLogModel::LogInfoEvent('/cron/' . $cron, $msg); // It needs to return something. $log = new CronLogModel(); $log->set('status', 'fail'); return $log; } // First, check and see if there's one that's still running. $runninglogs = CronLogModel::Find(array('cron' => $cron, 'status' => 'running')); if (sizeof($runninglogs)) { foreach ($runninglogs as $log) { /** @var $log CronLogModel */ $log->set('status', 'fail'); $log->set('log', $log->get('log') . "\n------------\nTIMED OUT!"); $log->save(); } } // Start recording. $log = new CronLogModel(); $log->set('cron', $cron); $log->set('status', 'running'); $log->set('memory', memory_get_usage()); $log->set('ip', REMOTE_IP); $log->save(); $start = microtime(true) * 1000; $sep = '==========================================' . "\n"; $contents = "Starting cron execution for {$cron}\n{$sep}"; // This uses the hook system, but will be slightly different than most things. $overallresult = true; $hook = HookHandler::GetHook('/cron/' . $cron); $hookcount = 0; $hooksuccesses = 0; if ($hook) { if ($hook->getBindingCount()) { $hookcount = $hook->getBindingCount(); $bindings = $hook->getBindings(); foreach ($bindings as $b) { $contents .= sprintf("\nExecuting Binding %s...\n", $b['call']); // Since these systems will just be writing to STDOUT, I'll need to capture that. try { ob_start(); $execution = $hook->callBinding($b, array()); $executiondata = ob_get_clean(); } catch (Exception $e) { $execution = false; $executiondata = 'EXCEPTION: ' . $e->getMessage() . ob_get_clean(); } if ($executiondata == '' && $execution) { $contents .= "Cron executed successfully with no output\n"; ++$hooksuccesses; } elseif ($execution) { $contents .= $executiondata . "\n"; ++$hooksuccesses; } else { $contents .= $executiondata . "\n!!FAILED\n"; $overallresult = false; } } } else { $contents = 'No bindings located for requested cron'; $overallresult = true; } } else { $contents = 'Invalid hook requested: ' . $cron; $overallresult = false; } // Just in case the contents are returning html... (they should be plain text). // Replace the most common line endings with things that make sense for plain text. // This is to ensure that all the available scenarios are met and saved/displayed without extra whitespace. // // Since some systems will provide plain text (easy!), windows/os9 line endings, // HTML (br and br/), and formatted HTML (br + \n). $contents = str_ireplace(["\r\n<br>", "\r\n<br/>", "\r\n<br />", "\n<br>", "\n<br/>", "\n<br />", "<br>", "<br/>", "<br />", "\r\n", "\r"], "\n", $contents); // Save the results. $log->set('completed', Time::GetCurrentGMT()); $log->set('duration', microtime(true) * 1000 - $start); $log->set('log', $contents); $log->set('status', $overallresult ? 'pass' : 'fail'); $log->save(); // Make a copy of this in the system log too if applicable. // This time is listed in ms $time = microtime(true) * 1000 - $start; // 0.01 = 10 ns // 1 = 1 ms // 1000 = 1 second if ($time < 1) { // TIME is less than 1, which means it executed faster than 1ms, display in nanoseconds. $time = round($time, 4) * 1000 . ' ns'; } elseif ($time < 1000) { // TIME is less than 1000, which means it executed faster than 1 second, display in milliseconds. $time = round($time, 0) . ' ms'; } else { // TIME is at least 1 second or longer... Display in minutes:seconds, (no need to display 1.453 seconds!) // First, convert the milliseconds to seconds; they are more manageable for what I need to do. // This will change time from 12345(ms) to 13(seconds) $time = ceil($time / 1000); $minutes = floor($time / 60); $seconds = $time - $minutes * 60; if ($minutes > 0) { $time = $minutes . 'm ' . str_pad($seconds, 2, '0', STR_PAD_LEFT) . 's'; } else { $time = $seconds . ' seconds'; } } if ($hookcount > 0) { $msg = 'Cron ' . $cron . ' completed in ' . $time . '. ' . $hooksuccesses . ' out of ' . $hookcount . ' hooks called successfully.'; SystemLogModel::LogInfoEvent('/cron/' . $cron, $msg, $contents); } // Just to notify the calling function. return $log; }
/** * Internally used method to notify the rest of the system that a given * component has been loaded and is available. * * Expects all checks to be done already. */ public function _registerComponent(Component_2_1 $c) { $name = str_replace(' ', '-', strtolower($c->getName())); if ($c->hasLibrary()) { $liblist = $c->getLibraryList(); $this->_libraries = array_merge($this->_libraries, $liblist); // Register the include paths if set. foreach ($c->getIncludePaths() as $path) { set_include_path(get_include_path() . PATH_SEPARATOR . $path); } } $this->_scriptlibraries = array_merge($this->_scriptlibraries, $c->getScriptLibraryList()); if ($c->hasModule()) $this->_modules[$name] = $c->getVersionInstalled(); $this->_classes = array_merge($this->_classes, $c->getClassList()); $this->_viewClasses = array_merge($this->_viewClasses, $c->getViewClassList()); $this->_widgets = array_merge($this->_widgets, $c->getWidgetList()); $this->_components[$name] = $c; // Permissions were not enabled prior to 2.1, so the legacy components do not have the function. if($c instanceof Component_2_1){ $this->_permissions = array_merge($this->_permissions, $c->getPermissions()); ksort($this->_permissions); // Register this component's user authdrivers, if any. $auths = $c->getUserAuthDrivers(); foreach($auths as $name => $class){ \Core\User\Helper::$AuthDrivers[$name] = $class; } } // All models get a control link registered automatically :) $models = $c->getModelList(); foreach($models as $class => $file){ if(!HookHandler::GetHook('/core/controllinks/' . $class)){ $h = new Hook('/core/controllinks/' . $class); $h->returnType = Hook::RETURN_TYPE_ARRAY; $h->description = 'Automatic hook for control links on the ' . $class . ' object. Attach onto this hook if you want to add a custom link anytime this object\'s control is displayed.'; } } $licenser = $c->getLicenseData(); if($licenser && defined('SERVER_ID') && class_exists('\\Core\\Licenser')){ // This will contain a url key and the features. $url = $licenser['url']; $comp = $c->getKeyName(); foreach($licenser['features'] as $key){ \Core\Licenser::RegisterFeature($key, $url, $comp); } } // Lastly, mark this component as available! $c->_setReady(true); }