Пример #1
0
 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'));
 }
Пример #2
0
 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;
 }
Пример #3
0
 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;
 }
Пример #4
0
 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')));
 }
Пример #5
0
 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);
 }
Пример #6
0
 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);
 }
Пример #7
0
 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));
 }
Пример #8
0
 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);
 }
Пример #9
0
 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];
 }
Пример #10
0
 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);
 }
Пример #11
0
 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);
 }
Пример #12
0
 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);
 }
Пример #14
0
 public function setup()
 {
     parent::setup();
     Conf::set('session_storage', '\\photon\\session\\storage\\File');
 }
Пример #15
0
 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());
 }
Пример #16
0
 /**
  * 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);
 }
Пример #17
0
 /**
  * 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);
     }
 }
Пример #18
0
 /**
  * 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;
 }
Пример #19
0
 /**
  * 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', ''));
 }
Пример #20
0
 * 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);
}
Пример #21
0
 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);
 }
Пример #22
0
 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);
 }
Пример #23
0
 /**
  * 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);
 }
Пример #24
0
 public function tearDown()
 {
     Conf::load($this->conf);
 }
Пример #25
0
 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;
 }
Пример #26
0
 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);
 }
Пример #27
0
 public function testLoadLocaleWithPhoton()
 {
     Conf::set('locale_folders', array('locale_dummyapp'));
     $pos = Translation::loadLocale('fr', true);
     $this->assertEquals(2, count($pos));
 }
Пример #28
0
 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;
 }
Пример #29
0
 /**
  * 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.
     }
 }
Пример #30
0
 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);
 }