public function handleException($exception) { // load the renderer $render = \Painless::load('system/common/render'); var_dump($exception); die; }
public function info($message) { if (Painless::isProfile(\Painless::DEV)) { $this->open(); fwrite($this->file, "{$message}\n"); } }
public function response($status, $message, $payload = array()) { $response = \Painless::load('system/workflow/response', \Painless::LP_LOAD_NEW); $response->status = (int) $status; $response->message = $message; $response->payload = $payload; return $response; }
public function get() { if (!empty($this->operations)) { // Run the workflows foreach ($this->operations as $operation) { $response = Painless::exec($operation); } } }
public function response($status = 0, $message = '', $payload = array()) { if ($status instanceof \Painless\System\Workflow\Response) { $this->response = $status; } elseif (is_int($status)) { $this->response = \Painless::manufacture('response', $status, $message, $payload); } return $this->response; }
public static function init() { // Check if there's a trigger configuration $config = \Painless::load('system/common/config'); $triggers = $config->get('triggers.*'); if (!empty($triggers)) { foreach ($triggers as $name => $callback) { self::register($name, $callback); } } }
/** * Redirects either to an external resource or to an internal workflow * @param string $path the path to redirect to */ protected function redirect($path) { $path = strtolower($path); // check if this is an external path if (stripos($path, 'http://') === FALSE && stripos($path, 'https://') === FALSE) { $path = \Painless::app()->env(\Painless::APP_URL) . $path; } // rebuild the response $response =& $this->response; $response->status = 302; $response->message = "Redirect"; $response->set(self::PATH, $path); }
/** * Adds a new config key into morphine * @return void */ public function addConfig($key, $value) { // Get the config DAO $dao = \Painless::app()->load('dao/config/config/sqlite'); // Set the values $dao->key = $key; $dao->value = $value; $id = $dao->new(); if (empty($id)) { return $this->response(400, "Unable to create new config key-value item for `{$key}` (value = {$value})"); } return $this->response(200, 'OK', array('id' => $id)); }
/** * Retrieves a topic from the help topic template directory * - 200 -> topic found * - 404 -> topic not found * @param string $topic the name of the topic to search for * @return PainlessResponse a response object detailing the status of the operation */ public function getTopic($topic) { // Try to get the topic try { ob_start(); \Painless::app()->load("tpl/help/{$topic}", LP_DEF_ONLY); $topic = ob_get_flush(); } catch (\ErrorException $e) { // Return a topic not found return $this->response(404, $topic . ' not found'); } return $this->response(200, 'Found', array('help' => $topic)); }
public function get() { // See what help is being requested $topic = $this->request->getParam(0); if (empty($topic)) { $topic = 'help'; } // Check if the topic is supported $model = \Painless::app()->load('model/help/topic'); $response = $model->getTopic($topic); // Do nothing because there's no logic to handle. Let view handle it. $this->response($response); }
protected function init() { // Localize all external variables $core = \Painless::app(); $appPath = $core->env(\Painless::APP_PATH); $appName = $core->env(\Painless::APP_NAME); $configPath = ''; $profile = ''; $aclPath = ''; // first, check if a deployment profile is issued $profile = $core->env(\Painless::PROFILE); // get the engine's implementor path if possible if (!empty($appPath)) { $configPath = $appPath . 'config/' . $appName; $aclPath = $appPath . 'config/' . $appName; $routesPath = $appPath . 'config/' . $appName; if ($profile) { $configPath .= '.' . $profile; } $configPath .= '.php'; $aclPath .= '.acl.php'; $routesPath .= '.route.php'; } // check if the config path is correct if (file_exists($configPath)) { require_once $configPath; if (!isset($config)) { throw new \ErrorException('Unable to find the config array in [' . $configPath . ']'); } $this->config = $config; // clean up because $config is going to be recycled after this unset($config); } else { throw new \ErrorException('Invalid config file [' . $configPath . ']'); } // load the acl array too if (file_exists($aclPath)) { require_once $aclPath; if (isset($config)) { $this->config = array_merge($this->config, $config); unset($config); } } // load the routes array too if (file_exists($routesPath)) { require_once $routesPath; if (isset($config)) { $this->config = array_merge($this->config, $config); } } }
public function get() { # GET execute/model/[module name]/[model name]/[params ...] // Get the model's module and name $module = $this->request->getParam('name'); $model = $this->request->getParam('name'); $params = $this->request->getParam('params'); // Get the model $model = \Painless::app()->load("model/{$module}/{$model}"); if (empty($model)) { return $this->response(404, 'Model not found'); } // Get the parameters }
/** * Returns a list of actions supported by this workflow * @return array an array of actions/methods supported by this workflow */ public function options() { $request = \Painless::load('system/common/router/response'); $methods = $request->getMethodList(); // Run through the list of methods supported by the request object and then // cross-reference them to the list of methods available on this workflow. // If they don't exist, simply remove them from the method list and then // return the result. This would give the caller a good idea of what kind // of functions that particular workflow supports. $supported = array(); foreach ($methods as $i => $method) { if (!method_exists($this, $method)) { $supported[] = $methods[$i]; } } return $methods; }
public function open($options = array()) { // do not proceed if memcached is not available if (!extension_loaded('memcached')) { throw new \ErrorException('Memcached is not installed in your system.'); } $this->params = $options; // as usual, get the options from the config if not specified if (empty($this->params)) { $config = \Painless::app()->load('system/common/config'); $this->params = $config->get('memcached.*'); } // open a connection $host = array_get($this->params, 'memcached.host', FALSE); $port = (int) array_get($this->params, 'memcached.port', FALSE); $timeout = (int) array_get($this->params, 'memcached.timeout', FALSE); $this->conn = new Memcache(); return $this->conn->connect($host, $port, $timeout); }
public function regenerateSessionId() { // get dependencies. $security = \Painless::load('system/common/security'); $config = \Painless::load('system/common/config'); // get hash algorithm to use for session key generation. $hashAlgo = $config->get('session.id.hash_algo'); // Save the existing session's data. $existingSessionData = $_SESSION; session_write_close(); $newSessionId = $security->uniqueHash($hashAlgo); session_id($newSessionId); // unable to regenerate session ID. Need to re-test this soon. session_start(); // Save the existing session data back to current session. $_SESSION = $existingSessionData; return $newSessionId; }
<?php // Attempt to load PUPUnit. If it fails, we are done. if (!@(include_once 'PHPUnit/Autoload.php')) { die(PHP_EOL . 'PHPUnit does not appear to be installed properly.' . PHP_EOL . 'Please visit http://phpunit.de and re-install.' . PHP_EOL . PHP_EOL); } /** * Set error reporting and display errors settings. You will want to change these when in production. */ error_reporting(E_ALL | E_STRICT); ini_set('display_errors', 1); // Bootstrap Painless PHP require_once __DIR__ . "/../painless/painless.php"; Painless::initApp('core', '/');
/** * Loads an adapter * @param array $nsa an array of tokens from the namespace string * @param string $ns the namespace string in full * @return array the meta data on how to load the component */ protected function adapter($nsa, $ns) { // Throw an exception of $nsa does not meet the correct length req. if (count($nsa) < 2) { throw new \ErrorException('Adapter namespace should follow this format: adapter/[adapter]'); } // The second key in the $nsa array is always the module name, followed // by the dao name $adapter = $nsa[1]; // Load the base class first \Painless::load('system/data/adapter/base', \Painless::LP_DEF_ONLY); return array('extpath' => $this->appPath . 'system/data/adapter/' . $adapter . EXT, 'extname' => '\\' . dash_to_pascal($this->appName) . '\\System\\Data\\Adapter\\' . dash_to_pascal($adapter), 'basepath' => $this->corePath . 'system/data/adapter/' . $adapter . EXT, 'basename' => '\\Painless\\System\\Data\\Adapter\\' . dash_to_pascal($adapter)); }
public function dispatch() { // Check and load the router $router = \Painless::app()->load('system/common/router'); // Process the command line arguments into a proper URI $uri = $this->processArgs(); try { // Let the router process the business logic $response = $router->process($uri); } catch (PainlessWorkflowNotFoundException $e) { // Construct a 404 response $response = \Painless::app()->load('system/workflow/response', LP_LOAD_NEW); $response->status = 404; $response->message = 'Unable to locate workflow'; } catch (\ErrorException $e) { $response = \Painless::app()->load('system/workflow/response', LP_LOAD_NEW); $response->status = 500; $response->message = $e->getMessage(); } // Pass the control to the renderer $render = \Painless::app()->load('system/common/render'); $output = $render->process($response); return $output; }
/** * Processes the request and response to compile the right output * @param Request $request a request object * @param Response $response a response object * @return mixed an output compiled by the appropriate compiler */ public function process($request, $response) { // Localize the variables $view = NULL; $method = $request->method; $module = $request->module; $controller = $request->controller; $contentType = $request->contentType; // If $module and $controller exists, find the View controller if (!empty($module) && !empty($controller)) { // Load the correct view $view = \Painless::load("view/{$module}/{$controller}"); // If the view does not exists, return a 404 if (!empty($view)) { $view->request = $request; $view->response = $response; // Get the output from the view by running the appropriate method. Once // the method has been run, it's safe to assume that $view has properly // post-processed all necessary data and payload, and that now the // compiler should have enough information to render the output if ($view->preProcess()) { $view->{$method}(); } $view->postProcess(); } } // At this point, if the view is NULL, create a default view just to // pacify the angry view compiler. if (empty($view)) { $view = \Painless::load('system/view/view', \Painless::LP_LOAD_NEW); $view->request = $request; $view->response = $response; } // Load the appropriate view compiler $compiler = \Painless::load("system/view/compiler/{$contentType}"); // If the content type is not suppoted, $compiler will be NULL. Handle // the error here if (NULL === $compiler) { // Use the default HTML compiler $compiler = \Painless::load("system/view/compiler/html"); } // Return the processed output as a response; return $compiler->process($view); }
public function sql() { if (empty(self::$queryBuilder)) { self::$queryBuilder = \Painless::load('system/data/sql/sql-factory'); } return self::$queryBuilder; }
public function execute($entry, $cmd = '', $data = array(), $role = array()) { // Here we need to determine the entry point. There are only 3 of them: // HTTP (includes REST calls), CLI (including cron jobs) and APP. The // first two are fairly self-explanatory, but APP needs more explanation // on this front. // // When a request to APP is made, Painless would automatically convert it // to either HTTP or APP. First it'll look inside the app registry, and // check the app's path. If the path starts with a http://, it'll convert // the call to a HTTP call instead, and if not, it'll assume its a file // path and use APP as is. // // Example: // Painless::request( 'GET app://flight-plan/id/123' ); // will first search for the app's path inside the registry, and // if it looks like this: // $config['apps']['flight-plan'] = '/usr/local/web/htdocs/flight-plan'; // then it is a local call, and if it looks like this: // $config['apps']['flight-plan'] = 'http://flight-plan.foo.com:8003'; // then it is a REST call. // Load the router into the Core registry $router = \Painless::load('system/common/router'); // Localize the response variable $response = FALSE; // Log the entry point, which would return a sequence number $seq = $this->log('protocol', $entry, 0); // Send the command to the router to process, which will create a request // object containing all routing information (as well as some extra info // like agent string, content type, etc) if (\Painless::RUN_HTTP === $entry || \Painless::RUN_CLI === $entry || \Painless::RUN_APP === $entry || \Painless::RUN_INTERNAL) { // Send the router the command to receive a request $request = $router->process($entry, $cmd, $data, $role); // By now $cmd is an array. Change it back to a string $cmd = implode('/', $cmd); // Set this request as the active one $this->active = $request; // Log the request $this->log('request', $request, $seq); // If $request is FALSE, something baaaaadddddd has happened inside // the router. Use a 500 error response instead of dispatching it. if (FALSE === $request) { $response = \Painless::manufacture('response', 500, 'Fatal error when trying to process the command in router. See log for more details.'); } elseif (empty($request->module)) { $response = \Painless::manufacture('response', 404, "Module not found for the command: [{$cmd}]"); } elseif (empty($request->controller)) { $response = \Painless::manufacture('response', 404, "Controller not found for the command: [{$cmd}]"); } else { $response = $router->dispatch($request); } } else { // Manufacture an empty request $request = \Painless::manufacture('request', '', '', ''); // Set this request as the active one $this->active = $request; // Log the request $this->log('request', $request); // Manufacture a 500 error status response object $response = \Painless::manufacture('response', 500, 'Invalid entry point'); } // Make sure $response is the correct type if (!$response instanceof \Painless\System\Workflow\Response) { $response = \Painless::manufacture('response', 500, 'Invalid returned response'); } // Log the response object $this->log('response', $response, $seq); // Get the renderer $render = \Painless::load('system/common/render'); // Process the request and response to get an output $response = $render->process($request, $response); // Log the response object generated by the renderer $this->log('output', $response, $seq); // Now we can safely assume that $response has all the necessary headers // and payload. We return this to the invoking agent to render it. return $response; }
public function destroy() { \Painless::load('system/common/session')->destroy(); $this->identity = NULL; }
/** * Edits a config key in morphine * @return void */ public function post() { // Get the config model $model = \Painless::app()->load('model/config/manager'); // Get the key to update and the value $key = $this->request->getParam('key'); $value = $this->request->getParam('value'); // Try to update the config key $response = $model->updateConfig($key, $value); // Handle the return status if ($response->status === 200) { $this->response(200, 'OK'); return; } else { $this->response($response); return; } }
/** * Processes the URI and returns the parameter array, as well as mapping out * module, workflow, and content type * @param array $uri the URI in an array * @return array an array of $module, $controller, $params and * $contentType */ protected function mapUri(array &$uri) { // Grab dependencies $config = \Painless::load('system/common/config'); // Localize the variables $module = ''; $controller = ''; $contentType = ''; $params = array(); $command = $uri; // Load the URI format from the routes config $routes = $config->get('routes.uri.config'); // Use the default routing if not configured (auto-routing) if (!is_array($routes)) { $routes = $this->defaultRoute; } // Process the URI list $count = count($uri); for ($i = 0; $i < $count; $i++) { // If the $uri segment is empty (most probably caused by double // backslashes - //), remove it from the array if (empty($uri[$i])) { unset($uri[$i]); continue; } if (isset($routes[$i])) { $con = $routes[$i]; if ('alias' === $con) { // Get the workflow and module mapping, and then append the // rest of the URI into the params array. No point proceeding // further as alias don't play well with module and workflow $routeMap = $config->get('routes.alias'); if (isset($routeMap[$uri[$i]])) { list($module, $controller) = $routeMap[$uri[$i]]; } // Only do this if this is not the end of the URI array if ($i !== $count) { $params = array_values(array_merge($params, array_slice($uri, $i + 1))); break; } } elseif ('module' === $con) { // Grab the module $module = $uri[$i]; } elseif ('controller' === $con) { // Grab the controller $controller = $uri[$i]; } elseif ('param' === $con) { $params[] = $uri[$i]; } } else { $params = array_values(array_merge($params, array_slice($uri, $i))); break; } } // Now, we try to determine the content type by checking the last URI // segment for a dotted notation $count = count($params); if ($count > 0) { $last = $params[$count - 1]; $pos = strpos($last, '.'); if (FALSE !== $pos) { // extract the content type from the segment $contentType = substr($last, $pos + 1); // Make sure the content type is valid if (empty($contentType)) { $contentType = 'html'; } // remove the content type from the last URI segment $params[$count - 1] = substr($last, 0, $pos); } } // Ensure that module and controller are defined. If they are not, try to // load them from the config file if (empty($module) && empty($uri[0])) { $module = $config->get('routes.uri.default.module'); } if (empty($controller) && empty($uri[0])) { $controller = $config->get('routes.uri.default.controller'); } return array($module, $controller, $params, $contentType); }
public function send() { $this->init(); $config = \Painless::load('system/common/config'); $smtpServer = $config->get('email.host'); $port = $config->get('email.port'); $timeout = $config->get('email.timeout'); $mailbox = $this->mailbox; if ('' === $mailbox) { $mailbox = 'default'; } // Get the correct email mailbox profile $fromName = $config->get("email.{$mailbox}.from_name"); $fromAddress = $config->get("email.{$mailbox}.from_address"); $username = $config->get("email.{$mailbox}.username"); $password = $config->get("email.{$mailbox}.password"); // Connect to the host on the specified port $smtpConnect = fsockopen($smtpServer, $port, $errno, $errstr, $timeout); fgets($smtpConnect, 515); if (empty($smtpConnect)) { return FALSE; } $newLine = "\r\n"; // Request Auth Login fputs($smtpConnect, "AUTH LOGIN" . $newLine); fgets($smtpConnect, 515); // Send username fputs($smtpConnect, base64_encode($username) . $newLine); $ret = fgets($smtpConnect, 515); if (stripos($ret, 'error') !== FALSE) { return FALSE; } // Send password fputs($smtpConnect, base64_encode($password) . $newLine); $ret = fgets($smtpConnect, 515); if (stripos($ret, 'error') !== FALSE) { return FALSE; } // Say Hello to SMTP fputs($smtpConnect, "HELO {$smtpServer}" . $newLine); fgets($smtpConnect, 515); // Email From $from = $fromAddress; fputs($smtpConnect, "MAIL FROM: {$from}" . $newLine); fgets($smtpConnect, 515); // Email To // includes all to, cc, bcc addresses. $count = count($this->to); for ($i = 0; $i < $count; ++$i) { $toAddress = $this->to[$i]['address']; fputs($smtpConnect, "RCPT TO: {$toAddress}" . $newLine); fgets($smtpConnect, 515); } $count = count($this->cc); for ($i = 0; $i < $count; ++$i) { $ccAddress = $this->cc[$i]['address']; fputs($smtpConnect, "RCPT TO: {$ccAddress}" . $newLine); fgets($smtpConnect, 515); } $count = count($this->bcc); for ($i = 0; $i < $count; ++$i) { $bccAddress = $this->bcc[$i]['address']; fputs($smtpConnect, "RCPT TO: {$bccAddress}" . $newLine); fgets($smtpConnect, 515); } // The Email fputs($smtpConnect, "DATA" . $newLine); fgets($smtpConnect, 515); // if "text/html" is sent, send along a plain text version as well for great compatibility. if (self::HTML === $this->contentType) { $randomHash = md5(date('r', time())); $toStr = $this->generateTo(); $ccStr = $this->generateCc(); $bccStr = $this->generateBcc(); $plainTextContent = strip_tags($this->content); // TODO: need better html stripper than this $subject = $this->subject; $content = $this->content; $charset = $this->charset; // Construct Headers $headers = "MIME-Version: 1.0" . $newLine; $headers .= "Subject: {$subject}" . $newLine; $headers .= "From: {$fromName} <{$fromAddress}>" . $newLine; $headers .= "To: {$toStr}" . $newLine; $headers .= "Cc: {$ccStr}" . $newLine; $headers .= "Bcc: {$bccStr}" . $newLine; $headers .= "Content-Type: multipart/alternative; boundary={$randomHash}" . $newLine; $headers .= "--{$randomHash}" . $newLine; $headers .= "Content-Type: text/plain; charset=ISO-8859-1" . $newLine; $headers .= "{$plainTextContent}" . $newLine; $headers .= "--{$randomHash}" . $newLine; $headers .= "Content-Type: text/html; charset=\"{$charset}\"" . $newLine; $headers .= "{$content}" . $newLine; $headers .= "--{$randomHash}--" . $newLine; fputs($smtpConnect, "{$headers}.\n"); fgets($smtpConnect, 515); } else { // Construct Headers $headers = "MIME-Version: 1.0" . $newLine; $contentType = $this->contentType; $charset = $this->charset; $encoding = $this->encoding; $headers .= "Content-Type: {$contentType}; charset=\"{$charset}\"" . $newLine; $headers .= "Content-transfer-encoding: {$encoding}" . $newLine; $toStr = $this->generateTo(); $ccStr = $this->generateCc(); $bccStr = $this->generateBcc(); $subject = $this->subject; $content = $this->content; fputs($smtpConnect, "To: {$toStr}\nCc: {$ccStr}\nBcc: {$bccStr}\nFrom: {$fromName} <{$fromAddress}>\nSubject: {$subject}\n{$headers}\n{$content}\n.\n"); fgets($smtpConnect, 515); } // Say Bye to SMTP fputs($smtpConnect, "QUIT" . $newLine); fgets($smtpConnect, 515); return TRUE; }
/** * Initializes an application * @param string $appName the name of the application (dash-delimited) * @param string $appPath the path of the application (dash-delimited) * @param boolean $useExtLoader set to TRUE to have the loader check for the * existence of an extended loader inside the * app's extensions, or FALSE to save time and * cycles */ public static function initApp($appName, $appPath, $useExtLoader = TRUE) { // Append a backslash to $implPath if none is provided $appPath[strlen($appPath) - 1] !== '/' and $appPath .= '/'; // Instantiate the Core. Here's the thing - both Core (which contains // instances of components, environment variables, etc) and Loader (which // handles loading of components) can be extended by the App, and thus // we will need to do some creative loading here. // // First, check if there's an extended version of a loader inside the // app's extensions. If there is (and $useExtLoader is set to TRUE), // instantiate that and use it to load the Core. Then save the loader // into Core. $loaderPath = __DIR__ . '/system/common/loader' . EXT; require_once $loaderPath; $core = \Painless\System\Common\Loader::init($appName, $appPath, __DIR__ . '/', $useExtLoader); // Register the app \Painless::app($appName, $core); // Set the registered app as the active one static::$curr = $appName; // Register an autoloader spl_autoload_register('\\Painless\\System\\Common\\Loader::autoload'); return $core; }
protected function handle500($request, $response) { $response->set(self::TPL_PATH, \Painless::app()->env(\Painless::APP_PATH) . 'view/error-500.tpl'); return $response; }