Typically, libraries and plugins are registered in app/config/bootstrap/libraries.php.
By convention, vendor libraries are typically located in app/libraries or /libraries, and
plugins are located in app/libraries/plugins or /libraries/plugins. By default, Libraries
will use its own autoloader for all plugins and vendor libraries, but can be configured to use
others on a case-by-case basis.
Libraries also handles service location. Various 'types' of classes can be defined by name,
using _class patterns_, which define conventions for organizing classes, i.e. 'models' is
'{:library}\models\{:name}', which will find a model class in any registered app, plugin or
vendor library that follows that path (namespace) convention. You can find classes by name (see
locate() for more information on class-locating precedence), or find all models in all
registered libraries (apps / plugins / vendor libraries, etc). For more information on modifying
the default class organization, or defining your own class types, see the paths() method.
/** * Compiles a template and writes it to a cache file, which is used for inclusion. * * @param string $file The full path to the template that will be compiled. * @param array $options Options for compilation include: * - `path`: Path where the compiled template should be written. * - `fallback`: Boolean indicating that if the compilation failed for some * reason (e.g. `path` is not writable), that the compiled template * should still be returned and no exception be thrown. * @return string The compiled template. */ public static function template($file, array $options = array()) { $cachePath = Libraries::get(true, 'resources') . '/tmp/cache/templates'; $defaults = array('path' => $cachePath, 'fallback' => false); $options += $defaults; $stats = stat($file); $oname = basename(dirname($file)) . '_' . basename($file, '.php'); $oname .= '_' . ($stats['ino'] ?: hash('md5', $file)); $template = "template_{$oname}_{$stats['mtime']}_{$stats['size']}.php"; $template = "{$options['path']}/{$template}"; if (file_exists($template)) { return $template; } $compiled = static::compile(file_get_contents($file)); if (is_writable($cachePath) && file_put_contents($template, $compiled) !== false) { foreach (glob("{$options['path']}/template_{$oname}_*.php", GLOB_NOSORT) as $expired) { if ($expired !== $template) { unlink($expired); } } return $template; } if ($options['fallback']) { return $file; } throw new TemplateException("Could not write compiled template `{$template}` to cache."); }
protected function _tempFileWithContents($contents) { $path = Libraries::get(true, 'resources') . '/tmp/' . uniqid() . '.php'; $this->_files[] = $path; file_put_contents($path, $contents); return $path; }
/** * Add a tests to the group * * @param string $test * @param string $options * @return array */ public function add($test = null, $options = array()) { $callback = function ($test) { if (empty($test)) { return array(); } if (is_object($test) && $test instanceof \lithium\test\Unit) { return array(get_class($test)); } if (is_string($test)) { if ($test[0] != '\\') { $test = "lithium\\tests\\cases\\{$test}"; } if (preg_match("/Test/", $test)) { return array($test); } $parts = array_filter(explode("\\", $test)); $library = array_shift($parts); $test = Libraries::find($library, array('recursive' => true, 'path' => '/' . join('/', $parts), 'filter' => '/cases|intergration|functional/')); return (array) $test; } return (array) $test; }; if (is_array($test)) { foreach ($test as $t) { $this->_items = array_filter(array_merge($this->_items, $callback($t))); } return $this->_items; } return $this->_items = array_merge($this->_items, $callback($test)); }
/** * Read the configuration or access the connections you have set up. * * Usage: * {{{ * // Gets the names of all available configurations * $configurations = Connections::get(); * * // Gets the configuration array for the connection named 'db' * $config = Connections::get('db', array('config' => true)); * * // Gets the instance of the connection object, configured with the settings defined for * // this object in Connections::add() * $dbConnection = Connections::get('db'); * * // Gets the connection object, but only if it has already been built. * // Otherwise returns null. * $dbConnection = Connections::get('db', array('autoCreate' => false)); * }}} * * @param string $name The name of the connection to get, as defined in the first parameter of * `add()`, when the connection was initially created. * @param array $options Options to use when returning the connection: * - `'autoCreate'`: If `false`, the connection object is only returned if it has * already been instantiated by a previous call. * - `'config'`: If `true`, returns an array representing the connection's internal * configuration, instead of the connection itself. * @return mixed A configured instance of the connection, or an array of the configuration used. */ public static function get($name = null, array $options = array()) { static $mockAdapter; $defaults = array('config' => false, 'autoCreate' => true); $options += $defaults; if ($name === false) { if (!$mockAdapter) { $class = Libraries::locate('data.source', 'Mock'); $mockAdapter = new $class(); } return $mockAdapter; } if (!$name) { return array_keys(static::$_configurations); } if (!isset(static::$_configurations[$name])) { return null; } if ($options['config']) { return static::_config($name); } $settings = static::$_configurations[$name]; if (!isset($settings[0]['object'])) { if (!$options['autoCreate']) { return null; } } return static::adapter($name); }
public function testCustomConfiguration() { $config = array( 'session.name' => 'awesome_name', 'session.cookie_lifetime' => 1200, 'session.cookie_domain' => 'awesome.domain', 'session.save_path' => Libraries::get(true, 'resources') . '/tmp/', 'somebad.configuration' => 'whoops' ); $adapter = new Php($config); $result = ini_get('session.name'); $this->assertEqual($config['session.name'], $result); $result = ini_get('session.cookie_lifetime'); $this->assertEqual($config['session.cookie_lifetime'], (integer) $result); $result = ini_get('session.cookie_domain'); $this->assertEqual($config['session.cookie_domain'], $result); $result = ini_get('session.cookie_secure'); $this->assertFalse($result); $result = ini_get('session.cookie_httponly'); $this->assertTrue($result); $result = ini_get('session.save_path'); $this->assertEqual($config['session.save_path'], $result); $result = ini_get('somebad.configuration'); $this->assertFalse($result); }
public static function find(array $options = array()) { $defaults = array('collect' => true); $options += $defaults; $data = array(); $libs = Libraries::get(null, 'path'); $recursive = true; foreach ($libs as $lib => $path) { $result = array(); $path .= '/views/widgets'; $files = StaticContents::available(compact('path', 'recursive')); if (!$files) { continue; } $temp = array_keys(Set::flatten($files, array('separator' => '/'))); foreach ($temp as $key => $value) { if (strpos($value, 'admin.') !== false) { continue; } if (strpos($value, 'inc.') !== false) { continue; } $result[$key] = str_replace('.html.php', '', $value); } $data[$lib] = $result; } return $data; }
public function testConfig() { $oldConfig = Libraries::get('li3_facebook'); Libraries::remove('li3_facebook'); Libraries::add('li3_facebook'); FacebookProxy::$_autoConfigure = false; FacebookProxy::__init(); $this->assertEqual(FacebookProxy::config(), array(), 'config should be empty.'); $this->assertEqual(FacebookProxy::config(array()), array(), 'config should be empty.'); //check ignoring FacebookProxy::reset(); $result = FacebookProxy::config(array('foo')); $this->assertTrue($result, array(), 'config should return true'); $this->assertIdentical(FacebookProxy::config(), array(), 'config should be empty'); //check ingoring vs. existing but unset associations FacebookProxy::reset(); $result = FacebookProxy::config(array('appId')); $this->assertTrue($result, array(), 'config should return true'); $this->assertIdentical(FacebookProxy::config(), array(), 'config should be empty'); //check valid Settings FacebookProxy::reset(); $sampleConfig = array('appId' => 'hello'); $result = FacebookProxy::config($sampleConfig); $this->assertTrue($result, 'config should return true'); $this->assertIdentical(FacebookProxy::config(), $sampleConfig, 'config should not be empty'); //check vs. complete Settings FacebookProxy::reset(); $result = FacebookProxy::config($this->_mockDefaults); $this->assertTrue($result, 'config should return true'); $this->assertIdentical(FacebookProxy::config(), $this->_mockDefaults, 'config should not be empty'); Libraries::remove('li3_facebook'); Libraries::add('li3_facebook', $oldConfig); //FaceBookProxy::foo(); //die(print_r(array($result,FacebookProxy::config()),true)); }
public function setUp() { $this->_backup['catalogConfig'] = Catalog::config(); Catalog::reset(); Catalog::config(array('lithium' => array('adapter' => 'Php', 'path' => Libraries::get('lithium', 'path') . '/g11n/resources/php'))); Validator::__init(); }
public static function config($name = null) { if (empty(self::$_config)) { $config = Libraries::get('li3_varnish'); $env = Environment::get(); if (isset($config[$env])) { $config += $config[$env]; unset($config[$env]); } foreach ($config as $k => $v) { if (isset(self::$_defaults[$k]) && is_array(self::$_defaults[$k])) { $config[$k] += self::$_defaults[$k]; } } self::$_config = $config + self::$_defaults; } if (isset($name)) { if (isset(self::$_config[$name])) { return self::$_config[$name]; } else { return null; } } return self::$_config; }
/** * Get content of file, parse it with lessc and return formatted css * * @todo allow for css-file name only, and search it in all avail. webroots * @param string $file full path to file * @param array $options Additional options to control flow of method * - header - controls, whether to prepend a header * - cache - controls, whether to cache the result * - cachePath - Where to cache files, defaults to * resources/tmp/cache * @return string|boolean generated css, false in case of error */ public static function file($file, array $options = array()) { $defaults = array('header' => true, 'cache' => true, 'cachePath' => Libraries::get(true, 'resources') . '/tmp/cache', 'cacheKey' => Inflector::slug(str_replace(array(LITHIUM_APP_PATH, '.less'), array('', '.css'), $file))); $options += $defaults; $css_file = $options['cachePath'] . '/' . $options['cacheKey']; if (file_exists($css_file) && filemtime($css_file) >= filemtime($file)) { return file_get_contents($css_file); } if (!file_exists($file)) { return false; } try { $less = static::_getLess($file); $output = $less->parse(); } catch (Exception $e) { $output = "/* less compiler exception: {$e->getMessage()} */"; } if ($options['header']) { $output = static::_prependHeader($output); } if ($options['cache']) { file_put_contents($css_file, $output); } return $output; }
/** * Perform initialization. * * @return void */ protected function _init() { Object::_init(); $type = isset($this->_config['type']) ? $this->_config['type'] : null; if ($type === 'text') { $h = function ($data) { return $data; }; } else { $encoding = 'UTF-8'; if ($this->_message) { $encoding =& $this->_message->charset; } $h = function ($data) use(&$encoding) { return htmlspecialchars((string) $data, ENT_QUOTES, $encoding); }; } $this->outputFilters += compact('h') + $this->_config['outputFilters']; foreach (array('loader', 'renderer') as $key) { if (is_object($this->_config[$key])) { $this->{'_' . $key} = $this->_config[$key]; continue; } $class = $this->_config[$key]; $config = array('view' => $this) + $this->_config; $path = 'adapter.template.mail'; $instance = Libraries::instance($path, $class, $config); $this->{'_' . $key} = $instance; } }
public function tearDown() { $_SERVER = $this->_backup['_SERVER']; chdir($this->_backup['cwd']); Libraries::add('app', $this->_backup['app']); $this->_cleanUp(); }
/** * Constructor. * * Takes care of setting appropriate configurations for this object. * * @param array $config Optional configuration parameters. * @return void */ public function __construct(array $config = array()) { if (empty($config['name'])) { $config['name'] = basename(Libraries::get(true, 'path')) . 'cookie'; } parent::__construct($config + $this->_defaults); }
/** * Constructor. * * @see lithium\util\String::insert() * @param array $config Settings used to configure the adapter. Available options: * - `'path'` _string_: The directory to write log files to. Defaults to * `<app>/resources/tmp/logs`. * - `'timestamp'` _string_: The `date()`-compatible timestamp format. Defaults to * `'Y-m-d H:i:s'`. * - `'file'` _\Closure_: A closure which accepts two parameters: an array * containing the current log message details, and an array containing the `File` * adapter's current configuration. It must then return a file name to write the * log message to. The default will produce a log file name corresponding to the * priority of the log message, i.e. `"debug.log"` or `"alert.log"`. * - `'format'` _string_: A `String::insert()`-compatible string that specifies how * the log message should be formatted. The default format is * `"{:timestamp} {:message}\n"`. * @return void */ public function __construct(array $config = array()) { $defaults = array('path' => Libraries::get(true, 'resources') . '/tmp/logs', 'timestamp' => 'Y-m-d H:i:s', 'file' => function ($data, $config) { return "{$data['priority']}.log"; }, 'format' => "{:timestamp} {:message}\n"); parent::__construct($config + $defaults); }
public function tearDown() { $_SERVER = $this->_backup['_SERVER']; chdir($this->_backup['cwd']); Libraries::remove('library_test'); unset($this->library, $this->request); }
/** * */ public function flush() { $this->_header(); $success = false; $config = Libraries::get('app'); $dir = TwigAdapter::cachePath(); $trash = $config['resources'] . self::PATH_TO_REMOVE; $this->out('Starting cache flush.'); if (!is_dir($dir)) { return $this->error('Cache folder not found... exiting.'); } $this->out('Cache folder found : ' . $dir); if (is_dir($trash)) { $this->out('Old trash folder found (previous command failure possible), deleting it...'); $this->_rrmdir($trash); } $this->out('Moving cache folder to temporary location...'); rename($dir, $trash); $this->out('Deleting temporary cache location...'); $success = $this->_rrmdir($trash); if (!$success) { return $this->error('Error while deleting Twig template cache.'); } return $this->out('Success!'); }
public function testDeliverLogToDir() { $path = realpath(Libraries::get(true, 'resources') . '/tmp/tests'); $this->skipIf(!is_writable($path), "Path `{$path}` is not writable."); $log = $path . DIRECTORY_SEPARATOR . 'mails'; if (!is_dir($log)) { mkdir($log); } $glob = $log . DIRECTORY_SEPARATOR . '*.mail'; $oldresults = glob($glob); $options = array('to' => 'foo@bar', 'subject' => 'test subject'); $message = new Message($options); $debug = new Debug(); $format = 'short'; $delivered = $debug->deliver($message, compact('log', 'format')); $this->assertTrue($delivered); $results = array_diff(glob($glob), $oldresults); $this->assertEqual(1, count($results)); $resultFile = current($results); $result = file_get_contents($resultFile); $pattern = '\\[[\\d:\\+\\-T]+\\]'; $info = ' Sent to foo@bar with subject `test subject`.\\n'; $expected = '/^' . $pattern . $info . '$/'; $this->assertPattern($expected, $result); unlink($resultFile); }
public function setUp() { $this->_path = $path = Libraries::get(true, 'resources') . '/tmp/tests'; mkdir("{$this->_path}/en/LC_MESSAGES", 0755, true); mkdir("{$this->_path}/de/LC_MESSAGES", 0755, true); $this->adapter = new MockGettext(compact('path')); }
protected function _init() { parent::_init(); $this->_config = (array) Libraries::get('li3_pecl_oauth'); $this->_config += array('host' => $this->request->env('SERVER_NAME'), 'oauth_callback' => $this->request->env('SERVER_NAME') . '/oauth/client', 'namespace' => 'li3_pecl_oauth', 'redirect_success' => 'Client::index', 'redirect_failed' => array('Client::index', 'args' => array('failed' => true))); return Consumer::config($this->_config) ? true : false; }
public function view() { $date = $this->request->date; $channel = '#' . $this->request->channel; $year = date('Y', strtotime($date)); if (!in_array($channel, LogMessages::channels())) { throw new Exception('Unknown channel.'); } $baseUrl = array('library' => 'li3_bot', 'controller' => 'logs'); $breadcrumbs[] = array('title' => 'Channel Logs', 'url' => $baseUrl + array('action' => 'channels')); $breadcrumbs[] = array('title' => $channel, 'url' => null); $breadcrumbs[] = array('title' => $year, 'url' => array('library' => 'li3_bot', 'controller' => 'logs', 'action' => 'index', 'channel' => ltrim($channel, '#')) + compact('year')); $breadcrumbs[] = array('title' => date('m/d', strtotime($date)), 'url' => null); $messages = LogMessages::day($channel, $date); $previous = date('Y-m-d', strtotime($date) - 60 * 60 * 24); $next = date('Y-m-d', strtotime($date) + 60 * 60 * 24); if (!LogMessages::hasDay($channel, $previous)) { $previous = null; } if (!LogMessages::hasDay($channel, $next)) { $next = null; } $rewriters = Libraries::get('li3_bot', 'rewriters'); return compact('channel', 'messages', 'date', 'breadcrumbs', 'previous', 'next', 'rewriters'); }
/** * Magic method to make Controller callable. * * @see lithium\action\Dispatcher::_callable() * @param object $request A \lithium\action\Request object. * @param array $dispatchParams Array of params after being parsed by router. * @param array $options Some basic options for this controller. * @return string */ public function __invoke($request, $dispatchParams, array $options = array()) { $dispatchParamsDefaults = array('args' => array()); $dispatchParams += $dispatchParamsDefaults; $defaults = array('reporter' => 'html', 'format' => 'html'); $options += (array) $request->query + $defaults; $params = compact('request', 'dispatchParams', 'options'); set_time_limit(0); return $this->_filter(__METHOD__, $params, function ($self, $params) { $request = $params['request']; $options = $params['options']; $params = $params['dispatchParams']; $group = join('\\', (array) $params['args']); if ($group === "all") { $group = Group::all(); $options['title'] = 'All Tests'; } $report = Dispatcher::run($group, $options); $filters = Libraries::locate('test.filter'); $menu = Libraries::locate('tests', null, array('filter' => '/cases|integration|functional/', 'exclude' => '/mocks/')); sort($menu); $result = compact('request', 'report', 'filters', 'menu'); return $report->render('layout', $result); }); }
public function index() { $title = 'Testing Leaderboard'; $options = Libraries::get('li3_leaderboard'); $data = StatsPresenter::find('all', $options); return compact('data', 'title'); }
public function setUp() { $this->_path = Libraries::get(true, 'resources') . '/tmp/tests'; $template1 = '<' . '?php echo $foo; ?' . '>'; $template2 = '<' . '?php echo $this["foo"]; ?' . '>'; file_put_contents("{$this->_path}/template1.html.php", $template1); file_put_contents("{$this->_path}/template2.html.php", $template2); }
public function __construct($options = array()) { $this->_library = Libraries::get('li3_hierarchy'); $this->_cacheDir = $this->_library['path'] . '/resources/tmp/cache'; $defaults['cache'] = Environment::get() == 'production' ? true : false; $this->_options = $this->_library + $defaults; $this->_cache = $this->_options['cache']; }
/** * Skip the test if the default File adapter read/write path is not read/write-able. * * @return void */ public function skip() { $this->configuration['path'] = Libraries::get(true, 'resources') . '/tmp/tests'; $directory = new SplFileInfo($this->configuration['path']); $accessible = $directory->isDir() && $directory->isReadable() && $directory->isWritable(); $message = 'The File filesystem adapter path does not have the proper permissions.'; $this->skipIf(!$accessible, $message); }
protected function _init() { parent::_init(); $class = Libraries::locate('socket.util', $this->_classes['socket']); if (is_string($class)) { $this->_connection = new $class($this->_config); } }
/** * Finds the test case for the corresponding class name. * * @param string $class A fully-namespaced class reference for which to find a test case. * @return string Returns the class name of a test case for `$class`, or `null` if none exists. */ public static function get($class) { $parts = explode('\\', $class); $library = array_shift($parts); $name = array_pop($parts); $type = "tests.cases." . implode('.', $parts); return Libraries::locate($type, $name, compact('library')); }
/** * Grab a the `layout.html.php` template and return output * * @param string $template name of the template (eg: layout) * @param string $data array from `_data()` method * @return string */ protected function _render($template, $data) { $template = Libraries::locate('test.reporter.template', $template, array('filter' => false, 'type' => 'file', 'suffix' => '.html.php')); extract($data); ob_start(); include $template; return ob_get_clean(); }
/** * Finds a library for given path. * * @return string|void The library's name on success. */ protected function _library($path) { foreach (Libraries::get() as $name => $library) { if (strpos($path, $library['path']) === 0) { return $name; } } }
public function testError() { $base = Libraries::get(true, 'resources') . '/tmp/tests'; $this->skipIf(!is_writable($base), "Path `{$base}` is not writable."); $response = new Response(array('error' => fopen($this->streams['error'], 'w+'))); $this->assertInternalType('resource', $response->error); $this->assertEqual(2, $response->error('ok')); $this->assertEqual('ok', file_get_contents($this->streams['error'])); }