public function __construct($conf = array()) { parent::__construct($conf); // Connect to each mongrel2 servers on port PUB & Control only // The worker do not want to receive HTTP requests from mongrel2 $servers = Conf::f('server_conf', null); if ($servers === null) { Log::fatal("No mongrel2 servers in the configuration"); Log::flush(); exit(0); } foreach ($servers as $serverId => $server) { // Ignore servers without control port if (isset($server['ctrl_addr']) === false || $server['ctrl_addr'] === null || isset($server['pub_addr']) === false || $server['pub_addr'] === null) { continue; } Log::info('Server #' . $serverId . ' Control = ' . $server['ctrl_addr'] . ' Pub = ' . $server['pub_addr']); $connection = new Connection(null, $server['pub_addr'], $server['ctrl_addr']); $connection->connect(); $this->connections[] = $connection; $this->jobs[] = array(); } if (count($this->connections) === 0) { Log::fatal('No mongrel2 servers with control port detected'); Log::flush(); exit(0); } Log::info('Task ready, ' . gmdate('c')); }
private function connectTask($name, $class = null) { if (null === self::$ctx) { return false; } if (isset(self::$sockets[$name])) { return true; } if ($class === null) { $tasks = Conf::f('installed_tasks', array()); $class = $tasks[$name]; } // We need to know if this is an async or sync task // We need to get the bind socket. $conf = Conf::f('photon_task_' . $name, array()); $bind = isset($conf['sub_addr']) ? $conf['sub_addr'] : SUB_ADDR; $type = isset($conf['type']) ? $conf['type'] : $class::$type; if ('async' === $type) { self::$sockets[$name] = new \ZMQSocket(self::$ctx, \ZMQ::SOCKET_DOWNSTREAM); self::$sockets[$name]->connect($bind); } else { self::$sockets[$name] = new \ZMQSocket(self::$ctx, \ZMQ::SOCKET_REQ); self::$sockets[$name]->connect($bind); } self::$types[$name] = $type; return true; }
public static function write($stack) { if (self::$isOpen === false) { $default = array('ident' => 'PhotonApp', 'facility' => LOG_USER, 'option' => LOG_CONS | LOG_NDELAY | LOG_PID); $conf = Conf::f('log_syslog', $default); $conf = array_merge($default, $conf); // Windows can log only in LOG_USER if (substr(PHP_OS, 0, 3) === 'WIN') { $conf['facility'] = LOG_USER; } $rc = openlog($conf['ident'], $conf['option'], $conf['facility']); if ($rc === true) { self::$isOpen = true; } } foreach ($stack as $elt) { $level = self::$photon2syslog[$elt[1]]; if (is_array($elt[2]) || is_object($elt[2])) { $msg = json_encode($elt[2]); } else { $msg = $elt[2]; } syslog($level, $msg); } return false; }
public function testUrlGenerate() { Conf::set('urls', array(array('regex' => '#^/home/(.+)/$#', 'view' => array('\\helloworld\\views\\Views', 'you'), 'name' => 'home'))); $this->assertequals('/home/', URL::generate('/home/')); $this->assertequals('/home/?p=foo', URL::generate('/home/', array('p' => 'foo'))); $this->assertequals('/home/?p=foo&b=bar', URL::generate('/home/', array('p' => 'foo', 'b' => 'bar'), false)); $this->assertequals('/home/?p=foo&b=bar', URL::generate('/home/', array('p' => 'foo', 'b' => 'bar'))); }
public function testRedirectToLogin() { $request = (object) array('method' => 'POST', 'path' => '/toto'); $res = new response\RedirectToLogin($request, '/login'); $this->assertSame(302, $res->status_code); Conf::set('urls', array(array('regex' => '#^/login$#', 'view' => array('Dummy', 'dummy'), 'name' => 'login_view'))); $res = new response\RedirectToLogin($request); $this->assertSame(302, $res->status_code); }
public function __construct() { $backendConfiguration = Conf::f('session_mongodb', array()); foreach ($backendConfiguration as $key => $value) { $this->{$key} = $value; } if ($this->database === null || $this->collection === null) { throw new Exception('Configuration missing or invalid for MongoDB Session Backend'); } $this->db = DB::get($this->database)->selectCollection($this->collection); }
public function testAuth() { Conf::set('auth_config_users', array('foo' => 'hashed', 'foobar' => Hash::hashPass('secret'))); $user = \photon\auth\Auth::authenticate(array('login' => 'foobar', 'password' => 'secret')); $this->assertEquals('foobar', $user->login); $req = \photon\test\HTTP::baseRequest(); $req->session = array(); $this->assertEquals(true, \photon\auth\Auth::login($req, $user)); $this->assertEquals(false, \photon\auth\Auth::login($req, false)); $user->is_anonymous = true; $this->assertEquals(false, \photon\auth\Auth::login($req, $user)); }
public function __construct() { $backendConfiguration = Conf::f('session_memcached', array()); foreach ($backendConfiguration as $key => $value) { $this->{$key} = $value; } $this->expire = Conf::f('session_cookie_expire', null); if ($this->database === null) { throw new Exception('Configuration missing or invalid for Memcached Session Backend'); } $this->db = DB::get($this->database); }
public static function get($db = 'default') { if (isset(self::$conns[$db]) === false) { $defs = Conf::f('databases', array()); if (!isset($defs[$db])) { throw new UndefinedConnection(sprintf('The connection "%s" is not defined in the configuration.', $db)); } $engine = $defs[$db]['engine']; self::$conns[$db] = $engine::get($defs[$db]); } return self::$conns[$db]; }
public function testPf() { Conf::set('mail_host', '127.0.0.1'); $mail = Conf::pf('mail_', true); $this->assertArrayHasKey('host', $mail); $this->assertequals($mail['host'], '127.0.0.1'); Conf::set('mail_port', 1234); $mail = Conf::pf('mail_', false); $this->assertequals(count($mail), 2); $this->assertArrayHasKey('mail_host', $mail); $this->assertArrayHasKey('mail_port', $mail); }
public function __construct($gridFsName, $filter = array()) { $databases = Conf::f('databases', array()); $config = Conf::f('storage-mongodb-object', array()); $dbName = isset($config['databases']) ? $config['databases'] : 'default'; if (!isset($databases[$dbName])) { throw new \photon\db\UndefinedConnection(sprintf('The connection "%s" is not defined in the configuration.', $dbName)); } $class = class_exists('\\MongoClient') ? '\\MongoClient' : '\\Mongo'; $conn = new $class($databases[$dbName]['server'], $databases[$dbName]['options']); $db = $conn->selectDB($databases[$dbName]['database']); $gridfs = $db->getGridFS($gridFsName); $ns = $databases[$dbName]['database'] . '.' . $gridFsName . '.files'; $fields = array(); parent::__construct($gridfs, $conn, $ns, $filter, $fields); }
public function testLog() { Log::setLevel('ALL'); Conf::set('log_delayed', true); Conf::set('log_handlers', array('\\photon\\log\\NullBackend')); $message = 'dummy message'; $i = 0; Log::plog($message); $i++; $this->assertEquals($i, count(Log::$stack)); Log::debug($message); $i++; $this->assertEquals($i, count(Log::$stack)); Log::info($message); $i++; $this->assertEquals($i, count(Log::$stack)); Log::perf($message); $i++; $this->assertEquals($i, count(Log::$stack)); Log::event($message); $i++; $this->assertEquals($i, count(Log::$stack)); Log::warn($message); $i++; $this->assertEquals($i, count(Log::$stack)); Log::error($message); $i++; $this->assertEquals($i, count(Log::$stack)); Log::fatal($message); $i++; $this->assertEquals($i, count(Log::$stack)); FileBackend::$return = true; Log::flush(); $this->assertEquals(0, count(Log::$stack)); FileBackend::$return = false; Log::flush(); $this->assertEquals(0, count(Log::$stack)); Log::flush(); $this->assertEquals(0, count(Log::$stack)); Conf::set('log_delayed', false); Log::info($message); $this->assertEquals(0, count(Log::$stack)); }
public function __construct($objectType, $filter = array(), $collectionName = null) { $this->objectType = $objectType; $objectType; if ($collectionName === null) { $collectionName = $objectType::collectionName; } else { $this->collectionName = $collectionName; } $databases = Conf::f('databases', array()); $config = Conf::f('storage-mongodb-object', array()); $dbName = isset($config['databases']) ? $config['databases'] : 'default'; if (!isset($databases[$dbName])) { throw new \photon\db\UndefinedConnection(sprintf('The connection "%s" is not defined in the configuration.', $db)); } $class = class_exists('\\MongoClient') ? '\\MongoClient' : '\\Mongo'; $conn = new $class($databases[$dbName]['server'], $databases[$dbName]['options']); $ns = $databases[$dbName]['database'] . '.' . $collectionName; $fields = array('_id' => 1); parent::__construct($conn, $ns, $filter, $fields); }
public function setup() { parent::setup(); Conf::set('session_storage', '\\photon\\session\\storage\\File'); }
public function testCustomTag() { $tags = Conf::f('template_tags', array()); $tags['relativity'] = '\\photon\\tests\\template\\rendererTest\\LocalTag'; Conf::set('template_tags', $tags); $renderer = new template\Renderer('data-template-custom-tag.html', array(__DIR__)); $this->assertequals("E=mc²\n", $renderer->render()); Conf::set('template_tags', array()); }
/** * Provide the full URL (without domain) to a view. * * @param string View. * @param array Parameters for the view (array()). * @param array Extra GET parameters for the view (array()). * @param bool Should the URL be encoded (true). * @return string URL. */ public static function forView($view, $params = array(), $get_params = array(), $encoded = true) { return self::generate(Conf::f('base_urls') . self::reverse(Conf::f('urls', array()), $view, $params), $get_params, $encoded); }
/** * Construct the compiler. * * @param $template_file string Basename of the template file * @param $folders array Source folders of the templates * @param $options array */ function __construct($template_file, $folders, $options = array()) { $this->_sourceFile = $template_file; $this->templateFolders = $folders; $options = array_merge(array('load' => true, 'tags' => array(), 'modifiers' => array()), $options); $this->_allowedTags = array_merge($this->_allowedTags, $options['tags'], Conf::f('template_tags', array())); Event::send('\\photon\\template\\compiler\\Compiler::construct_load_tags', null, $this->_allowedTags); $this->_modifier = array_merge($this->_modifier, $options['modifiers'], Conf::f('template_modifiers', array())); Event::send('\\photon\\template\\compiler\\Compiler::construct_load_modifiers', null, $this->_modifier); foreach ($this->_allowedTags as $name => $model) { $this->_extraTags[$name] = new $model(); } $this->_allowedInVar = array_merge($this->_vartype, $this->_op); $this->_allowedInExpr = array_merge($this->_vartype, $this->_op); $this->_allowedAssign = array_merge($this->_vartype, $this->_assignOp, $this->_op); if ($options['load']) { $this->sourceFiles[] = $this->loadTemplateFile($this->_sourceFile); } }
/** * Flush the stack to the disk. * * @param $stack Array */ public static function write($stack) { if (null === self::$log_file) { self::$log_file = Conf::f('photon_log_file', Conf::f('tmp_folder', sys_get_temp_dir()) . '/photon.log'); } $out = array(); foreach ($stack as $elt) { $out[] = date(DATE_ISO8601, $elt[0]) . ' [' . Log::$reverse[$elt[1]] . '] ' . json_encode($elt[2]); } file_put_contents(self::$log_file, implode(PHP_EOL, $out) . PHP_EOL, FILE_APPEND | LOCK_EX); if (!self::$chmoded) { @chmod($file, 0666); self::$chmoded = true; } return self::$return; }
/** * Request object provided to the Photon views. * * @param &$mess Mongrel2 request message object. */ function __construct(&$mess) { $this->mess = $mess; $this->path = $this->mess->path; $this->method = $this->mess->headers->METHOD; $this->sender = $this->mess->sender; $this->client = $this->mess->conn_id; $this->headers = $this->mess->headers; if (isset($this->mess->headers->QUERY)) { \mb_parse_str($this->mess->headers->QUERY, $this->GET); $this->query = $this->mess->headers->QUERY; } if ('POST' === $this->mess->headers->METHOD || 'PUT' === $this->mess->headers->METHOD) { if (isset($this->mess->headers->{'content-type'}) === false) { $this->BODY =& $mess->body; } else { if (0 === strpos($this->mess->headers->{'content-type'}, 'multipart/form-data; boundary=')) { $parser = new \photon\http\multipartparser\MultiPartParser($mess->headers, $mess->body); foreach ($parser->parse() as $part) { if ('FIELD' === $part['of_type']) { add_to_post($this->POST, $part['name'], $part['data']); } else { add_file_to_post($this->FILES, $part['name'], $part); } } } else { if (false !== mb_strstr($this->mess->headers->{'content-type'}, 'application/x-www-form-urlencoded')) { $this->POST = parse_str(substr(stream_get_contents($mess->body), 0, -1)); } else { $this->BODY =& $mess->body; } } } } else { if ('JSON' === $this->mess->headers->METHOD) { $this->BODY = $this->mess->body; } } $this->COOKIE = CookieHandler::parse($this->mess->headers, Conf::f('secret_key', '')); }
* But... PHPUnit accepts only one PHP prepend file. Good news, * PHPUnit can also set some php.ini values before the run. So, Photon * is calling PHPUnit with this bootstrap file and at the same time, * it passes PHPUnit the photon.config value with the path to the * config file for the unit tests. * * Of course, if you do not like this bootstrap file, you can run your * tests this way: * * $ photon runtests --bootstrap=path/to/yourbootstrap.php * * Also, by default, Photon will load the config.test.php file in your * current folder. You can change it by running: * * $ photon --conf=path/to/myconfig.php runtests * * You can combine them: * * $ photon --conf=fooconfig.php runtests --bootstrap=/other/testbootstrap.php * * WARNING: For added security, photon will never accept to run tests * against a config file named "config.php". This is to avoid the * "oops I run the tests against my production settings and I have * just dropped the main database.". */ namespace { include_once __DIR__ . '/autoload.php'; $tmp = is_dir(__DIR__ . '/../../tmp') ? realpath(__DIR__ . '/../../tmp') : sys_get_temp_dir(); $config = array('runtests' => true, 'tmp_folder' => $tmp, 'debug' => true, 'secret_key' => 'SECRET_KEY'); \photon\config\Container::load($config); }
public function __construct($request, $vars = array()) { $vars = array_merge(array('request' => $request), $vars); foreach (Conf::f('template_context_processors', array()) as $proc) { $vars = array_merge(call_user_func($proc, $request), $vars); } $this->_vars = new ContextVars($vars); }
public function testServerErrorWithTemplate() { $mess = (object) array('headers' => (object) array('QUERY' => 'a=b&c=d', 'METHOD' => 'GET'), 'path' => '/home', 'sender' => 'mongrel2', 'body' => '', 'conn_id' => '1234'); $req = new Request($mess); try { throw new \Exception('Bad exception', 123); } catch (\Exception $e) { } Conf::set('template_folders', array(__DIR__)); $res = new \photon\http\response\ServerError($e); $this->assertEquals('Server Error!' . "\n", $res->content); }
/** * Render a template file and an array as a reponse. * * @param $tmpl Template file name * @param $context Associative array for the context * @return Rendered template as a string */ public static function RenderToString($tmpl, $context) { $renderer = new ptemplate\Renderer($tmpl, Conf::f('template_folders')); $context = new ptemplate\Context($context); return $renderer->render($context); }
public function tearDown() { Conf::load($this->conf); }
private static function getConfig() { // Cache the config if (self::$config !== null) { return self::$config; } // Build the config $config = Conf::f('middleware_security', array()); $default = array('hsts' => false, 'hsts_options' => array('max-age' => 31536000, 'includeSubDomains' => true, 'preload' => true), 'hpkp' => false, 'hpkp_options' => array('pin-sha256' => array(), 'max-age' => 31536000, 'includeSubDomains' => true, 'report-uri' => false), 'ssl_redirect' => false); self::$config = array_replace_recursive($default, $config); return self::$config; }
public function testViewFoundInSub() { $views = array(array('regex' => '#^/hello#', 'sub' => array(array('regex' => '#^/home/(.+)/$#', 'view' => function () { return false; }, 'name' => 'home'))), array('regex' => '#^/foo/(.+)/$#', 'view' => function () { throw new \Exception(); }, 'name' => 'foo_bar')); Conf::set('urls', $views); $headers = (object) array('METHOD' => 'GET'); $msg = new Message('dummy', 'dummy', '/hello/home/foo/', $headers, ''); $req = new \photon\http\Request($msg); list($req, $resp) = Dispatcher::dispatch($req); $this->assertEquals(false, $resp); }
public function testLoadLocaleWithPhoton() { Conf::set('locale_folders', array('locale_dummyapp')); $pos = Translation::loadLocale('fr', true); $this->assertEquals(2, count($pos)); }
public static function isEmpty() { $config = Conf::f('storage-mongodb-object', array()); $db = isset($config['databases']) ? $config['databases'] : 'default'; $db = DB::get($db); $collection = $db->selectCollection($this->getCollectionName()); $it = $collection->find(); $it->limit(1); $it->rewind(); return $it->hasNext() === false; }
/** * Handles the signals. * * @param $signo The POSIX signal. */ public static function signalHandler($signo) { if (\SIGTERM === $signo) { Log::info('Received SIGTERM, now stopping.'); foreach (Conf::f('shutdown', array()) as $i) { call_user_func($i); } die(0); // Happy death, normally we run the predeath hook. } }
public function run() { $this->loadConfig(); $folders = Conf::f('template_folders', array()); $tmp_folder = sys_get_temp_dir() . '/' . uniqid('photon', true); @mkdir($tmp_folder); @touch($this->potfile); // Compile all template to generate PHP Code $already_compiled = array(); foreach ($folders as $folder) { foreach (\photon\path\Dir::listFiles($folder) as $tpl) { if (!in_array($tpl, $already_compiled)) { // Compile the template $compiler = new compiler\Compiler($tpl, $folders); $content = $compiler->compile(); // save it $output = $tmp_folder . '/' . $tpl; $directory = dirname($output); if (is_dir($directory) === false) { mkdir($directory, 0777, true); } file_put_contents($output, $content); $already_compiled[] = $tpl; } } } $return_var = 0; // Run xgettext on PHP project source $cmd = 'cd ' . $this->cwd . ' && find . -type f -iname "*.php" | sed -e \'s/^\\.\\///\' | xargs xgettext -o ' . $this->potfile . ' -p ' . $this->cwd . ' --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP'; passthru($cmd, $return_var); // Run xgettext on PHP project compiled template source $cmd = 'cd ' . $tmp_folder . ' && find . -type f | sed -e \'s/^\\.\\///\' | xargs xgettext -o ' . $this->potfile . ' -p ' . $this->cwd . ' --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP'; passthru($cmd, $return_var); \photon\path\Dir::remove($tmp_folder); }