/** * Initialize, load config and etc. */ private static function init() { if (static::$writers === null) { static::$writers = array(); $configs = Application::getConfig('application', 'log'); $count = 0; foreach ($configs as $config) { if ($config['enabled']) { // if the config is enabled, then make new instance $writer = $config['writer_class']; static::$writers[$count] = new $writer($config['options']); if (!static::$writers[$count] instanceof AbstractLogWriter) { throw new Exception("Log driver {$writer} must extend AbstractLogWriter"); } $count++; } } register_shutdown_function(function () { \Koldy\Log::shutdown(); }); } }
/** * (non-PHPdoc) * @see \Koldy\Application\Route\AbstractRoute::exec() */ public function exec() { if (method_exists($this->controllerInstance, 'before')) { $response = $this->controllerInstance->before(); // if "before" method returns anything, then we should not continue if ($response !== null) { return $response; } } $method = $this->getActionMethod(); if (method_exists($this->controllerInstance, $method) || method_exists($this->controllerInstance, '__call')) { // get the return value of your method (json, xml, view object, download, string or nothing) return $this->controllerInstance->{$method}(); } else { // the method we need doesn't exists, so, there is nothing we can do about it any more Log::notice("Can not find method={$method} in class={$this->getControllerClass()} on path={$this->controllerPath} for URI=" . Application::getUri()); static::error(404); } }
/** * Execute the query * * @param string $query * @param array $bindings OPTIONAL, but very recommended * @param integer $fetchMode pass only PDO::FETCH_* constants * @return boolean|int False if query failes; number of affected rows if query passed * * @link http://koldy.net/docs/database/basics#query * @link http://www.php.net/manual/en/pdo.constants.php */ public function query($query, array $bindings = null, $fetchMode = null) { $sql = is_object($query) ? $query->__toString() : trim($query); $this->lastQuery = $sql; $this->lastBindings = $bindings; $adapter = $this->getAdapter(); try { $stmt = $adapter->prepare($sql); } catch (PDOException $e) { // the SQL syntax might fail here $this->lastException = $e; $this->lastError = $e->getMessage(); throw $e; } $stmt->setFetchMode($fetchMode !== null ? $fetchMode : PDO::FETCH_OBJ); $logSql = false; try { if ($bindings === null) { $ok = $stmt->execute(); } else { $ok = $stmt->execute($bindings); } $logSql = true; } catch (PDOException $e) { $this->lastException = $e; $this->lastError = $e->getMessage(); throw $e; } $return = null; if ($ok) { if (strtoupper(substr($sql, 0, 6)) == 'SELECT') { $return = $stmt->fetchAll(); } else { $return = (int) $stmt->rowCount(); } } else { $return = false; } if (LOG && $logSql) { if ($this->configKey === null) { Log::sql($this->__toString()); } else { Log::sql("{$this->configKey}>>{$this->__toString()}"); } } return $return; }
/** * If you statically created new record in database to the table with auto * incrementing field, then you can use this static method to get the * generated primary key * * @return integer * @example * * if (User::create(array('first_name' => 'John', 'last_name' => 'Doe'))) { * echo User::getLastInsertId(); * } */ public static function getLastInsertId() { if (static::$autoIncrement) { return static::getAdapter(static::$connection)->getLastInsertId(); } else { Log::warning('Can not get last insert ID when model ' . get_called_class() . ' doesn\'t have auto_increment field'); return null; } }
public static function processRequest(array $params) { $data = $params; $params = array(); foreach ($data as $key => $value) { $params[strtolower($key)] = $value; } unset($data); $where = array(); $bindings = null; if (isset($params['package_name']) && $params['package_name'] !== null && trim($params['package_name']) != '') { $where[] = '(package IS NULL OR package LIKE :package_name)'; $bindings['package_name'] = "%{$params['package_name']}%"; } if (isset($params['app_version_name']) && $params['app_version_name'] !== null && trim($params['app_version_name']) != '') { $where[] = '(package_version IS NULL OR package_version LIKE :package_version)'; $bindings['package_version'] = "%{$params['app_version_name']}%"; } if (isset($params['android_version']) && $params['android_version'] !== null && trim($params['android_version']) != '') { $where[] = '(os_version IS NULL OR os_version LIKE :os_version)'; $bindings['os_version'] = "%{$params['android_version']}%"; } if (isset($params['brand']) && $params['brand'] !== null && trim($params['brand']) != '') { $where[] = '(brand IS NULL OR brand LIKE :brand)'; $bindings['brand'] = "%{$params['brand']}%"; } if (isset($params['phone_model']) && $params['phone_model'] !== null && trim($params['phone_model']) != '') { $where[] = '(model IS NULL OR model LIKE :model)'; $bindings['model'] = "%{$params['phone_model']}%"; } if (isset($params['product']) && $params['product'] !== null && trim($params['product']) != '') { $where[] = '(product IS NULL OR product LIKE :product)'; $bindings['product'] = "%{$params['product']}%"; } if (isset($params['country']) && $params['country'] !== null && trim($params['country']) != '') { $where[] = '(country IS NULL OR country LIKE :country)'; $bindings['country'] = "%{$params['country']}%"; } if (sizeof($where) == 0) { return false; } $where = implode(' AND ', $where); $query = "\n\t\t\tSELECT\n\t\t\t\tid,\n\t\t\t\tname,\n\t\t\t\tto_emails,\n\t\t\t\tlast_email,\n\t\t\t\temail_delay_minutes\n\t\t\tFROM\n\t\t\t\temail_trigger\n\t\t\tWHERE\n\t\t\t\t{$where}\n\t\t\t\tAND state = 'waiting'\n\t\t"; $records = static::getAdapter()->query($query, $bindings); foreach ($records as $r) { $send = false; $now = gmdate('Y-m-d H:i:s'); if ($r->last_email === null) { $send = true; } else { $then = new \DateTime($r->last_email); $then->modify("+{$r->email_delay_minutes} minute"); // Log::debug("{$then->format('Y-m-d H:i:s')} < {$now}"); if ($then->format('Y-m-d H:i:s') < $now) { $send = true; } } if ($send) { static::update(array('state' => 'sending'), $r->id); $email = Mail::create(); foreach (explode(',', $r->to_emails) as $address) { $email->to($address); } $email->subject($r->name); $body = array("DATE AND TIME (GMT): {$now}"); $body[] = "PACKAGE: {$params['package_name']} {$params['app_version_name']}"; unset($params['package_name'], $params['app_version_name']); // first append one line data foreach ($params as $key => $value) { $value = trim($value); if ($value != '') { if (strpos($value, "\n") === false) { $body[] = strtoupper($key) . ": {$value}"; unset($params[$key]); } } } if (isset($params['stack_trace'])) { $body[] = "STACK TRACE\n" . str_repeat('=', 30) . "\n" . $params['stack_trace']; unset($params['stack_trace']); } // append multiple line data foreach ($params as $key => $value) { $value = trim($value); if ($value != '') { $body[] = strtoupper($key) . "\n" . str_repeat('=', 30) . "\n" . $value; unset($params[$key]); } } $email->body(implode("\n\n", $body)); $email->from('no-reply@' . Request::hostName()); if ($email->send()) { Log::notice("Sent e-mail alert '{$r->name}'"); static::update(array('last_email' => $now, 'last_update' => $now, 'state' => 'waiting'), $r->id); } else { Log::error("Can not send e-mail alert '{$r->name}', sender returned false"); static::update(array('state' => 'waiting'), $r->id); } } } }
/** * Insert archive metas * @param array $metas */ public function insertMeta(array $metas) { $ok = array('report_id', 'environment', 'build', 'settings_global', 'settings_system', 'settings_secure', 'device_features', 'shared_preferences', 'initial_configuration', 'crash_configuration', 'dumpsys_meminfo', 'display', 'stack_trace', 'logcat', 'tktal_mem_size', '@evice_features', 'installation_id', 'file_path', 'dropbox', 'is_silent', 'custom_data'); foreach ($metas as $key => $value) { if (in_array($key, $ok)) { // first, insert into meta_archive to get last ID try { $meta = Meta::create(array('crash_id' => $this->id, 'name' => $key, 'value' => $value)); } catch (\Exception $e) { Log::error("Can not insert meta for={$this->id} key={$key} value={$value}"); Log::exception($e); \Status::setCalculationStatus('Died. Failed on meta table'); exit(1); } } else { // key is not recognized, but we'll still write it in database try { UnknownMeta::create(array('report_id' => $this->id, 'meta_name' => $key, 'meta_value' => $value)); } catch (\Exception $e) { Log::error("Can not insert unknown meta report_id={$this->id} meta_name={$key} meta_value={$value}"); Log::exception($e); \Status::setCalculationStatus('Died. Failed on unknown meta table'); exit(1); } } } }
/** * If your app throws any kind of exception, it will end up here, so, handle it! * * @param \Exception $e */ public function handleException(\Exception $e) { if (!headers_sent()) { header('HTTP/1.1 503 Service Temporarily Unavailable', true, 503); header('Status: 503 Service Temporarily Unavailable'); header('Retry-After: 300'); // 300 seconds / 5 minutes } if ($this->isAjax()) { Json::create(array('success' => false, 'type' => 'exception', 'exception' => Application::inDevelopment() ? $e->getMessage() : null, 'trace' => Application::inDevelopment() ? $e->getTraceAsString() : null))->flush(); } else { $file503 = Application::getPublicPath('503.php'); if (is_file($file503)) { $code = 503; $message = $e->getMessage(); $exception = $e; include $file503; } else { if (Application::inDevelopment()) { echo "<strong>{$e->getMessage()}</strong><pre>{$e->getTraceAsString()}</pre>"; } else { echo "<h1>Error</h1><p>Something went wrong. Please try again later!</p>"; } } } Log::exception($e); }
/** * Initialize the application :) * * @throws Exception */ protected static function init() { // second, check all requirements if (!function_exists('spl_autoload_register')) { throw new Exception('SPL is missing! Can not register autoload function'); } // set the error reporting in development mode if (static::inDevelopment()) { error_reporting(E_ALL | E_STRICT); } $config = static::getConfig('application'); // this is just shorthand for Directory Separator defined('DS') || define('DS', DIRECTORY_SEPARATOR); date_default_timezone_set($config['timezone']); // Register Autoload function spl_autoload_register(function ($className) { $classes = \Koldy\Application::$classAliases; if (isset($classes[$className])) { class_alias($classes[$className], $className); } else { $classPath = str_replace('\\', DS, $className); $path = "{$classPath}.php"; include $path; } }); // set the include path to the framework folder (to Koldy and any other // framework(s) located in framework folder with same namespacing style) $includePaths = array(substr(dirname(__FILE__), 0, -6)); $basePath = static::getApplicationPath(); // auto registering modules if there are any defined if (isset($config['auto_register_modules'])) { if (!is_array($config['auto_register_modules'])) { throw new Exception('Invalid config for auto_register_modules in config/application.php'); } foreach ($config['auto_register_modules'] as $moduleName) { $includePaths[] = $basePath . 'modules' . DS . $moduleName . DS . 'controllers'; $includePaths[] = $basePath . 'modules' . DS . $moduleName . DS . 'models'; $includePaths[] = $basePath . 'modules' . DS . $moduleName . DS . 'library'; } } // adding additional include paths if there are any if (isset($config['additional_include_path'])) { if (!is_array($config['additional_include_path'])) { throw new Exception('Invalid config for additional_include_path in config/application.php'); } // so, we need to include something more foreach ($config['additional_include_path'] as $path) { $includePaths[] = $path; } } // register include path of application itself $includePaths[] = $basePath . 'controllers'; $includePaths[] = $basePath . 'library'; $includePaths[] = $basePath . 'models'; // set the include path set_include_path(implode(PATH_SEPARATOR, $includePaths) . PATH_SEPARATOR . get_include_path()); // set the error handler if (isset($config['error_handler']) && $config['error_handler'] instanceof \Closure) { set_error_handler($config['error_handler']); } else { set_error_handler(function ($errno, $errstr, $errfile, $errline) { if (!(error_reporting() & $errno)) { // This error code is not included in error_reporting return; } switch ($errno) { case E_USER_ERROR: \Koldy\Log::error("PHP [{$errno}] {$errstr} in file {$errfile}:{$errline}"); break; case E_USER_WARNING: case E_DEPRECATED: case E_STRICT: \Koldy\Log::warning("PHP [{$errno}] {$errstr} in file {$errfile}:{$errline}"); break; case E_USER_NOTICE: \Koldy\Log::notice("PHP [{$errno}] {$errstr} in file {$errfile}:{$errline}"); break; default: \Koldy\Log::error("PHP Uknown [{$errno}] {$errstr} in file {$errfile}:{$errline}"); break; } /* Don't execute PHP internal error handler */ return true; }); } // register PHP fatal errors register_shutdown_function(function () { if (!defined('KOLDY_FATAL_ERROR_HANDLER')) { define('KOLDY_FATAL_ERROR_HANDLER', true); // to prevent possible recursion if you run into problems with logger $fatalError = error_get_last(); if ($fatalError !== null && $fatalError['type'] == E_ERROR) { $errno = E_ERROR; $errstr = $fatalError['message']; $errfile = $fatalError['file']; $errline = $fatalError['line']; $config = \Koldy\Application::getConfig('application'); if (isset($config['error_handler']) && $config['error_handler'] instanceof \Closure) { call_user_func($config['error_handler'], $errno, $errstr, $errfile, $errline); } else { \Koldy\Log::error("PHP [{$errno}] Fatal error: {$errstr} in {$errfile} on line {$errline}"); } } } }); // all execeptions will be caught in run() method }
/** * (non-PHPdoc) * @see SessionHandlerInterface::gc() */ public function gc($maxlifetime) { $delete = new Delete($this->config['table']); $timestamp = time() - $maxlifetime; if ($delete->where('time', '<', $timestamp)->exec($this->config['connection']) === false) { Log::error("Session GC: Error deleting session record from database that are older then maxlifetime={$maxlifetime} (older then timestamp {$timestamp})"); return false; } return true; }
/** * Process the request * @param string $os 'Android','iOS' or 'Windows' * * TODO: This logic shouldn't be in the model */ public static function processRequest($os) { if (!isset($_POST['PACKAGE_NAME'])) { Log::warning('Package name is not set! UAS=' . Request::userAgent() . ' POST=' . Json::encode($_POST)); } $time = time(); $ip = $_SERVER['REMOTE_ADDR']; $host = gethostbyaddr($ip); $country = null; $provider = null; if ($host != $ip && strpos($host, '.') !== false) { $country = strtolower(substr($host, strrpos($host, '.') + 1)); if (strlen($country) != 2) { $country = null; } $provider = \Provider::normalizeHostName($host); } Log::notice("Got request time={$time} host={$host} country={$country}"); $values = array('created_at', 'package_name', 'app_version_code', 'app_version_name', 'brand', 'phone_model', 'product', 'stack_trace', 'android_version', 'file_path', 'total_mem_size', 'available_mem_size', 'user_comment', 'user_app_start_date', 'user_crash_date', 'installation_id', 'report_id', 'user_email'); $data = array(); $vals = $_POST; foreach ($values as $key) { $key = strtoupper($key); if (isset($vals[$key])) { $data[$key] = trim($vals[$key]); unset($vals[$key]); } } if (isset($data['user_email']) && ($data['user_email'] == 'N/A' || trim($data['user_email']) == '')) { $data['user_email'] = null; } $data['created_at'] = gmdate('Y-m-d H:i:s'); $data['country'] = $country; $data['provider'] = $provider; $data['os'] = $os; $secureCount = 0; do { $submit = static::create($data); if ($submit === false) { Db::getAdapter()->close(); Log::info("Failed to insert crash submit report for time={$time}, waiting 5 seconds"); set_time_limit(60); sleep(5); Db::getAdapter()->reconnect(); Log::info("Retry {$secureCount} insert crash submit report for time={$time}"); } } while ($submit === false && $secureCount++ < 3); if ($submit !== false) { foreach ($vals as $metaName => $metaValue) { if ($metaValue !== null) { $metaValue = trim($metaValue); if (strlen($metaValue) > 0) { $secureCount = 0; do { $dbMeta = $submit->insertMeta(strtolower($metaName), trim($metaValue)); if ($dbMeta === false) { Db::getAdapter()->close(); Log::info("Failed to insert submit meta for meta={$metaName} time={$time}, waiting 5 seconds"); set_time_limit(60); sleep(5); Db::getAdapter()->reconnect(); Log::info("Retry {$secureCount} meta insert for meta={$metaName} time={$time}"); } } while ($dbMeta === false && $secureCount++ < 2); } } } } \Email\Trigger::processRequest($_POST); Log::notice("Done request time={$time}"); }
/** * Rebuild stack_trace table * CAUTION!!!! If you have a lot of records, this could take hours or days do get done! */ public static function rebuild() { Status::calculationStarted(); Status::setCalculationStatus('Initializing'); Status::setCalculationStatus('Reseting stack_trace_ids to NULL'); Db::query('UPDATE crash_archive SET stack_trace_id = NULL'); Status::setCalculationStatus('Emptying stack_trace table'); Db::query('TRUNCATE TABLE stack_trace'); $stacks = array(); // foreach (Stack\Trace::all() as $r) { // $stacks[$r['hash']] = (int) $r['id']; // } $total = \Crash\Archive::count(); $index = 0; $start = 0; do { $query = new Select('crash_archive'); $query->field('id')->where('id', '>', $start)->where('id', '<=', $start + 100000); Status::setCalculationStatus("Taking IDs from {$start} to " . ($start + 100000)); $records = $query->fetchAll(); $sizeofIds = count($records); foreach ($records as $r) { $id = (int) $r['id']; $crash = new \Crash\Archive(array('id' => $id)); $stackTrace = $crash->getMeta('stack_trace'); if ($stackTrace !== null) { $summary = static::getSummary($stackTrace); $md5 = md5($summary); if (isset($stacks[$md5])) { $stackTraceId = $stacks[$md5]; } else { $tmp = \Stack\Trace::create(array('hash' => $md5, 'summary' => $summary, 'created_at' => $crash->created_at)); $stackTraceId = (int) $tmp->id; $stacks[$md5] = $stackTraceId; } $crash->stack_trace_id = $stackTraceId; $crash->save(); Log::info("Updated #{$id} with stack={$stackTraceId}"); } else { Log::info("Crash report #{$id} is skipped because stack_trace is missing in meta table"); } if ($index % 25 == 0) { $percent = round($index / $total * 100, 2); Status::setCalculationStatus("Working on {$index}/{$sizeofIds} {$percent}%"); } $index++; } $start += 100000; } while (sizeof($records) > 0); Status::setCalculationStatus('Started stack trace recalculation!'); Log::info('Started recalculation of stack_trace counts'); static::recalculate(); Status::calculationFinished('all'); }
public function logAction() { Log::debug('TEST'); }
/** * Construct the object * @param string $uri */ public function __construct($uri, array $config = null) { if ($config === null || count($config) == 0 || !isset($config['module_param']) || !isset($config['controller_param']) || !isset($config['action_param'])) { throw new Exception('Route config options are missing'); } parent::__construct($uri, $config); if (isset($_GET[$config['controller_param']])) { $c = trim($_GET[$config['controller_param']]); if ($c == '') { $this->controllerUrl = 'index'; $this->controllerClass = 'IndexController'; } else { $this->controllerUrl = strtolower($c); $this->controllerClass = str_replace(' ', '', ucwords(str_replace(array('-', '.'), ' ', $this->controllerUrl))) . 'Controller'; } } else { $this->controllerUrl = 'index'; $this->controllerClass = 'IndexController'; } // Now we have the controller class name detected, but, should it be // taken from module or from default controllers? // TODO: Zavrsiti ovo! $moduleDir = Application::getApplicationPath() . 'modules' . DS . $this->controllerUrl; if (is_dir($moduleDir)) { // ok, it is a module with module/controller/action path $moduleUrl = $this->controllerUrl; $this->moduleUrl = $moduleUrl; $a = isset($_GET[$config['action_param']]) ? trim($_GET[$config['action_param']]) : ''; if ($a != '') { $this->controllerUrl = strtolower($a); $this->controllerClass = str_replace(' ', '', ucwords(str_replace(array('-', '.'), ' ', $this->controllerUrl))) . 'Controller'; } else { $this->controllerUrl = 'index'; $this->controllerClass = 'IndexController'; } $this->controllerPath = $moduleDir . DS . 'controllers' . DS . $this->controllerClass . '.php'; $mainControllerExists = true; if (!is_file($this->controllerPath)) { $this->controllerPath = Application::getApplicationPath() . 'modules' . DS . $moduleUrl . DS . 'controllers' . DS . 'IndexController.php'; if (!is_file($this->controllerPath)) { // Even IndexController is missing. Can not resolve that. if (Application::inDevelopment()) { $controllersPath = $moduleDir . DS . 'controllers'; \Koldy\Log::debug("Can not find {$this->controllerClass} nor IndexController in {$controllersPath}"); } Application::error(404, 'Page not found'); } $mainControllerExists = false; $this->controllerClass = 'IndexController'; } if ($mainControllerExists) { if (!isset($this->uri[3]) || $this->uri[3] == '') { $this->actionUrl = 'index'; $this->actionMethod = 'index'; } else { $this->actionUrl = strtolower($this->uri[3]); $this->actionMethod = ucwords(str_replace(array('-', '.'), ' ', $this->actionUrl)); $this->actionMethod = str_replace(' ', '', $this->actionMethod); $this->actionMethod = strtolower(substr($this->actionMethod, 0, 1)) . substr($this->actionMethod, 1); } } else { if (isset($this->uri[2]) && $this->uri[2] != '') { $this->actionUrl = strtolower($this->uri[2]); $this->actionMethod = ucwords(str_replace(array('-', '.'), ' ', $this->actionUrl)); $this->actionMethod = str_replace(' ', '', $this->actionMethod); $this->actionMethod = strtolower(substr($this->actionMethod, 0, 1)) . substr($this->actionMethod, 1); } else { $this->actionUrl = 'index'; $this->actionMethod = 'index'; } } // and now, configure the include paths according to the case Application::addIncludePath(array($moduleDir . DS . 'controllers' . DS, $moduleDir . DS . 'models' . DS, $moduleDir . DS . 'library' . DS, Application::getApplicationPath() . 'controllers' . DS, Application::getApplicationPath() . 'models' . DS, Application::getApplicationPath() . 'library' . DS)); } else { // ok, it is the default controller/action $this->controllerPath = Application::getApplicationPath() . 'controllers' . DS . $this->controllerClass . '.php'; $mainControllerExists = true; if (!is_file($this->controllerPath)) { $this->controllerPath = Application::getApplicationPath() . 'controllers' . DS . 'IndexController.php'; if (!is_file($this->controllerPath)) { // Even IndexController is missing. Can not resolve that. if (Application::inDevelopment()) { $controllersPath = Application::getApplicationPath() . 'controllers'; \Koldy\Log::debug("Can not find {$this->controllerClass} nor IndexController in {$controllersPath}"); } Application::error(404, 'Page not found'); } $mainControllerExists = false; $this->controllerClass = 'IndexController'; } if ($mainControllerExists) { if (!isset($this->uri[2]) || $this->uri[2] == '') { $this->actionUrl = 'index'; $this->actionMethod = 'index'; } else { $this->actionUrl = strtolower($this->uri[2]); $this->actionMethod = ucwords(str_replace(array('-', '.'), ' ', $this->actionUrl)); $this->actionMethod = str_replace(' ', '', $this->actionMethod); $this->actionMethod = strtolower(substr($this->actionMethod, 0, 1)) . substr($this->actionMethod, 1); } } else { $this->actionUrl = strtolower($this->uri[1]); $this->actionMethod = ucwords(str_replace(array('-', '.'), ' ', $this->actionUrl)); $this->actionMethod = str_replace(' ', '', $this->actionMethod); $this->actionMethod = strtolower(substr($this->actionMethod, 0, 1)) . substr($this->actionMethod, 1); } // and now, configure the include paths according to the case Application::addIncludePath(array(Application::getApplicationPath() . 'controllers' . DS, Application::getApplicationPath() . 'models' . DS, Application::getApplicationPath() . 'library' . DS)); } $this->isAjax = isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' || isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false; if ($this->isAjax) { $this->actionMethod .= 'Ajax'; } else { $this->actionMethod .= 'Action'; } }
/** * (non-PHPdoc) * @see \Koldy\Mail\Driver\AbstractDriver::send() */ public function send() { $from = $this->fromName !== null ? "{$this->fromName} <{$this->fromEmail}>" : $this->fromEmail; $to = ''; foreach ($this->to as $toUser) { $to .= $toUser['name'] !== null ? "{$toUser['name']} <{$toUser['email']}>" : $toUser['email']; $to .= ', '; } $to = substr($to, 0, -2); Log::info("E-mail [SIMULATED] is sent from {$from} to {$to} with subject: {$this->subject}"); return true; }
public function stackTracesAction() { Log::info('Started rebuilding stack traces'); Stack\Trace::rebuild(); }
public function logErrorAction() { Log::error('TEST ERROR'); }
/** * (non-PHPdoc) * @see \Koldy\Cache\Driver\AbstractDriver::deleteOld() */ public function deleteOld($olderThenSeconds = null) { if ($olderThenSeconds === null) { $olderThenSeconds = $this->defaultDuration; } clearstatcache(); /** * This is probably not good since lifetime is written in file * But going into every file and read might be even worse idea * XXX: Think about this */ foreach (Directory::read($this->path) as $fullPath => $fileName) { $timeCreated = @filemtime($fullPath); if ($timeCreated !== false) { // successfully red the file modification time if (time() - $olderThenSeconds > $timeCreated) { // it is old enough to be removed if (!@unlink($fullPath)) { Log::warning("Can not delete cached file on path {$fullPath}"); } } } } }
/** * Actually add new user into database */ public function addUserAjax() { $validator = Validator::create(array('id' => 'is:0', 'username' => "required|min:2|max:32|unique:\\User,username", 'first_name' => 'max:255', 'last_name' => 'max:255', 'pass' => 'required|min:5|max:255', 'pass2' => 'identical:pass', 'account_type' => 'required', 'timezone' => 'required')); if ($validator->failed()) { return BootstrapUI::formResponse()->failedOn($validator); } $data = $validator->getParams(); unset($data['id'], $data['pass2']); $data['pass'] = md5($data['pass']); $user = User::create($data); if ($user === false) { Log::error('Can not create new user'); return BootstrapUI::formResponse()->failed('Something went wrong'); } return BootstrapUI::formResponse()->redirect(Url::href('system', 'users')); }
/** * Calculate for reports * @return boolean */ public function calculate() { if (Status::isCalculationInProgress()) { Log::info('Trying to start calculation, but calculation is already in progress. Last was started on ' . Status::getLastCalculationProcessStart() . ' UTC'); return false; } ini_set('memory_limit', '512M'); set_time_limit(0); Status::calculationStarted(); Status::setCalculationStatus('Initializing'); Log::info('Calculation started'); /** * metas: 'file_path', 'build', 'environment', 'settings_global', 'settings_system', 'settings_secure', * 'device_features', 'shared_preferences', 'initial_configuration', 'crash_configuration', * 'dumpsys_meminfo', 'display', 'stack_trace', 'logcat', 'tktal_mem_size', '@evice_features', 'installation_id' */ $query = new Select(); $query->from('crash_submit')->field('id')->limit(0, 200000); $maxQuery = CrashArchive::query()->field('MAX(created_at)', 'time'); $max = $maxQuery->fetchFirstObj(); unset($maxQuery); $lastDatetime = new DateTime(gmdate('Y-m-d H:00:00')); $lastDatetime->modify('-1 hour'); $query->where('created_at', '<', $lastDatetime->format('Y-m-d H:i:s')); $ids = $query->fetchAllObj(); $sizeofIds = sizeof($ids); Log::info('Loaded ids: ' . $sizeofIds); $brandTotals = $countryTotals = $packageTotals = $packageVersionTotals = $phoneModelTotals = $productTotals = $providerTotals = $stackTraceTotals = $osVersionTotals = array(); foreach ($ids as $index => $r) { // on every 25 records, we should ask ourself: is that it? if ($index % 25 == 0) { $shouldTerminate = Status::shouldCalcuationTerminate(); if ($shouldTerminate !== false) { Log::info("Noticed request for calculation termination on {$shouldTerminate}. Aborted!"); Status::setCalculationStatus('Terminated after ' . ($index + 1) . ' records'); Status::terminateCalculation(false); return false; } } $id = $r->id; // record by record Log::info("Will now fetch id={$id}"); if ($index % 15 == 0) { $percent = round($index / $sizeofIds * 100, 2); Status::setCalculationStatus("Working; {$index}/{$sizeofIds} {$percent}%"); } $submit = CrashSubmit::fetchOne($id); if ($submit !== false && $submit->package_name !== null && trim($submit->package_name !== null) != '') { $appStartTime = strtotime($submit->user_app_start_date); $appCrashTime = strtotime($submit->user_crash_date); $appLifetime = $appCrashTime - $appStartTime; $metas = $submit->getMetas(); if ($submit->report_id !== null && trim($submit->report_id) !== '') { $metas['report_id'] = $submit->report_id; } if ($submit->file_path !== null && trim($submit->file_path) !== '') { $metas['file_path'] = $submit->file_path; } if ($submit->installation_id !== null && trim($submit->installation_id) !== '') { $metas['installation_id'] = $submit->installation_id; } $stackTrace = $submit->stack_trace; if ($stackTrace === null) { $stackTraceSummary = null; } else { $metas['stack_trace'] = $stackTrace; $stackTraceSummary = StackTrace::getSummary($stackTrace); } $packageId = $this->getPackageId($submit->package_name); $packageVersionId = $this->getPackageVersionId($this->getPackageId($submit->package_name), $submit->app_version_name); $brandId = $this->getBrandId($submit->brand); $phoneModelId = $this->getModelId($this->getBrandId($submit->brand), $submit->phone_model); $productId = $this->getProductId($this->getBrandId($submit->brand), $submit->product); $osVersionId = $this->getOsVersion($submit->os, $submit->android_version); $stackTraceId = $this->getStackTraceId($stackTraceSummary, $submit->created_at); $countryId = $this->getCountryId($submit->country); $providerId = $this->getProviderId($submit->provider); $archive = CrashArchive::create(array('created_at' => $submit->created_at, 'package_id' => $packageId, 'package_version_id' => $packageVersionId, 'brand_id' => $brandId, 'model_id' => $phoneModelId, 'product_id' => $productId, 'os' => $submit->os, 'os_version_id' => $osVersionId, 'total_mem_size' => $submit->total_mem_size, 'available_mem_size' => $submit->available_mem_size, 'user_comment' => trim($submit->user_comment) == '' ? null : trim($submit->user_comment), 'user_email' => trim($submit->user_email) == 'N/A' ? null : trim($submit->user_email), 'user_app_start_date' => $submit->user_app_start_date, 'user_crash_date' => $submit->user_crash_date, 'user_app_lifetime' => $appLifetime, 'stack_trace_id' => $stackTraceId, 'country_id' => $countryId, 'provider_id' => $providerId)); $archive->insertMeta($metas); // prepare increments for totals if ($packageId !== null) { if (!isset($packageTotals[$packageId])) { $packageTotals[$packageId] = 0; } $packageTotals[$packageId]++; } if ($packageVersionTotals !== null) { if (!isset($packageVersionTotals[$packageVersionId])) { $packageVersionTotals[$packageVersionId] = 0; } $packageVersionTotals[$packageVersionId]++; } if ($brandId !== null) { if (!isset($brandTotals[$brandId])) { $brandTotals[$brandId] = 0; } $brandTotals[$brandId]++; } if ($phoneModelId !== null) { if (!isset($phoneModelTotals[$phoneModelId])) { $phoneModelTotals[$phoneModelId] = 0; } $phoneModelTotals[$phoneModelId]++; } if ($productId !== null) { if (!isset($productTotals[$productId])) { $productTotals[$productId] = 0; } $productTotals[$productId]++; } if ($osVersionTotals !== null) { if (!isset($osVersionTotals[$osVersionId])) { $osVersionTotals[$osVersionId] = 0; } $osVersionTotals[$osVersionId]++; } if ($stackTraceId !== null) { if (!isset($stackTraceTotals[$stackTraceId])) { $stackTraceTotals[$stackTraceId] = 0; } $stackTraceTotals[$stackTraceId]++; } if ($countryId !== null) { if (!isset($countryTotals[$countryId])) { $countryTotals[$countryId] = 0; } $countryTotals[$countryId]++; } if ($providerId !== null) { if (!isset($providerTotals[$providerId])) { $providerTotals[$providerId] = 0; } $providerTotals[$providerId]++; } } } if ($sizeofIds > 0) { Log::info('Calculation done'); Status::setCalculationStatus('Starting to delete submit records'); $deleteIds = array(); foreach ($ids as $index => $r) { $deleteIds[] = $r->id; if (sizeof($deleteIds) == 100) { $percent = round($index / $sizeofIds * 100, 2); Status::setCalculationStatus("Deleting submit records {$index}/{$sizeofIds} {$percent}%"); Db::delete('crash_submit_meta')->whereIn('submit_id', $deleteIds)->exec(); Db::delete('crash_submit')->whereIn('id', $deleteIds)->exec(); $deleteIds = array(); } } if (sizeof($deleteIds) > 0) { Status::setCalculationStatus("Deleting submit records {$index}/{$sizeofIds} 100%"); Db::delete('crash_submit_meta')->whereIn('submit_id', $deleteIds)->exec(); Db::delete('crash_submit')->whereIn('id', $deleteIds)->exec(); } Status::setCalculationStatus('Started totals calculations update!'); // update calculated increments foreach ($brandTotals as $id => $total) { Status::setCalculationStatus('Brands: Updating calculated totals'); Db::update('brand')->increment('total', $total)->where('id', $id)->exec(); } foreach ($countryTotals as $id => $total) { Status::setCalculationStatus('Countries: Updating calculated totals'); Db::update('country')->increment('total', $total)->where('id', $id)->exec(); } foreach ($packageTotals as $id => $total) { Status::setCalculationStatus('Packages: Updating calculated totals'); Db::update('package')->increment('total', $total)->where('id', $id)->exec(); } foreach ($packageVersionTotals as $id => $total) { Status::setCalculationStatus('Package version: Updating calculated totals'); Db::update('package_version')->increment('total', $total)->where('id', $id)->exec(); } foreach ($phoneModelTotals as $id => $total) { Status::setCalculationStatus('Phone models: Updating calculated totals'); Db::update('phone_model')->increment('total', $total)->where('id', $id)->exec(); } foreach ($productTotals as $id => $total) { Status::setCalculationStatus('Products: Updating calculated totals'); Db::update('product')->increment('total', $total)->where('id', $id)->exec(); } foreach ($providerTotals as $id => $total) { Status::setCalculationStatus('Providers: Updating calculated totals'); Db::update('provider')->increment('total', $total)->where('id', $id)->exec(); } foreach ($stackTraceTotals as $id => $total) { Status::setCalculationStatus('Stack traces: Updating calculated totals'); Db::update('stack_trace')->increment('total', $total)->where('id', $id)->exec(); } foreach ($osVersionTotals as $id => $total) { Status::setCalculationStatus('OS version: Updating calculated totals'); Db::update('version')->increment('total', $total)->where('id', $id)->exec(); } } else { // Log::info('Calculation done, no records processed'); } Status::calculationFinished($sizeofIds); return true; }