/** * Interpolates a multi-dimensional array with another array recursively * * If no source is given, you get a live interpolation where you can directly interpolate * variables that have just been interpolated before * * Don't fetch the return value, the arrays are references. * If you want an unmutable version, rather take ArrayUtil::interpolate * * This is mostly used for option arrays, e.g. config-files * * We take both arrays as a reference to achieve a live-interpolation effect. * You can work with values you just interpolated before * e.g. [ 'path' => '{{rootPath}}/my/path', 'subPaths' => [ '{{path}}/sub/path' ] ] * * If you want to keep the original array, take a copy before * * @param array $array The array to interpolate (Passed by reference) * @param array|null $source The source array for variables. If none given, the input array is taken * @param null $defaultValue The default value for indices that couldnt be resolved * @param string $delimeter The delimeter used for multi-dimension access (Default: Dot (.)) * * @return array The interpolated array (Notice that it's just the same reference to the array you passed */ public static function interpolateMutable(array &$array, array &$source = null, $defaultValue = null, $delimeter = null) { if (!$source) { $source =& $array; } $newKeys = []; foreach ($array as $key => &$val) { if (is_string($key)) { $newKey = StringUtil::interpolate($key, $source, $defaultValue, $delimeter); if ($key !== $newKey) { $newKeys[$key] = $newKey; } } if (is_array($val)) { self::interpolateMutable($val, $source, $defaultValue, $delimeter); } else { if (is_string($val)) { $array[$key] = StringUtil::interpolate($val, $source, $defaultValue, $delimeter); } } } foreach ($newKeys as $key => $newKey) { $array[$newKey] = $array[$key]; unset($array[$key]); } return $array; }
private static function _setPhpOptions() { $options = Config::get('php-options', []); foreach ($options as $name => $value) { ini_set(StringUtil::dasherize($name, '.'), $value); } }
public function __construct($controller, $action, $format, array $args = null) { parent::__construct($format); //Sanitize names for consistent use $this->_controller = implode('.', array_map('Tale\\Util\\StringUtil::canonicalize', explode('.', $controller))); $this->_action = StringUtil::canonicalize($action); $this->_args = $args ? $args : []; }
public static function getHeaders() { foreach ($_SERVER as $name => $value) { if (strncmp($name, 'HTTP_', 5) === 0) { $name = StringUtil::dasherize(StringUtil::humanize(strtolower(substr($name, 5)))); (yield $name => $value); } } }
public function setCanonicalNameFromName() { $name = null; $i = 0; do { $addOn = ++$i >= 2 ? "-{$i}" : ''; $name = StringUtil::canonicalize($this->name) . $addOn; } while ($this->getTable()->where(['canonicalName' => $name])->count() > 0); $this->canonicalName = $name; return $name; }
public static function get($key = null, $default = null) { if (!$key) { return self::$_options; } if (strpos($key, '.') !== false) { if (!isset(self::$_resolvedOptions[$key])) { self::$_resolvedOptions[$key] = StringUtil::resolve($key, self::$_options, $default); } return self::$_resolvedOptions[$key]; } return isset(self::$_options[$key]) ? self::$_options[$key] : $default; }
public function resolveOption($key, $default = null, $delimeter = null) { return StringUtil::resolve($key, $this->getConfig()->getItems(), $default, $delimeter); }
private function _setPhpOptions() { foreach ($this->getOption('phpOptions') as $option => $value) { $option = StringUtil::tableize($option, '.'); ini_set($option, $value); } }
public function resolveMethodName($methodName) { return sprintf($this->_methodNamePattern, strpos($this->_methodNamePattern, '%s') === 0 ? StringUtil::variablize($methodName) : StringUtil::camelize($methodName)); }
public static function fromString($string) { $parts = StringUtil::mapReverse($string, ':', ['port', 'ip']); return new static(Address::fromString(trim($parts['ip'], '[]')), $parts['port']); }
public static function dispatch(array $request = null) { $request = array_replace(['module' => null, 'controller' => self::DEFAULT_CONTROLLER, 'action' => self::DEFAULT_ACTION, 'id' => null, 'args' => [], 'format' => self::DEFAULT_FORMAT], $request ? $request : []); //Sanitize (e.g. you can pass [sS]ome[-_][cC]ontroller, we want some-controller) $request['controller'] = StringUtil::canonicalize($request['controller']); $request['action'] = StringUtil::canonicalize($request['action']); $request['format'] = strtolower($request['format']); if ($request['id']) { array_unshift($request['args'], $request['id']); } $className = self::getClassName($request['controller'], $request['module']); $methodName = self::getMethodName($request['action']); var_dump("DISPATCH {$className}->{$methodName}", $request); try { if (!class_exists($className) || !is_subclass_of($className, __CLASS__)) { throw new \Exception("Failed to dispatch controller: {$className} doesnt exist or is not an instance of " . __CLASS__); } if (!method_exists($className, $methodName)) { throw new \Exception("Failed to dispatch action: {$className} has no method {$methodName}"); } } catch (\Exception $e) { if ($request['controller'] === self::ERROR_CONTROLLER) { throw $e; } self::dispatchError('not-found', array_merge(['exception' => $e], $request)); return; } $controller = new $className($request); //Get controllers init* methods $initMethods = call_user_func([$className, 'getInitMethodNames']); //Call all init*-Methods $result = null; foreach ($initMethods as $method) { $result = call_user_func([$controller, $method]); if ($result) { break; } } //Call the action if (!$result) { $result = call_user_func_array([$controller, $methodName], $request['args']); } //Let the dev be able to change the format in the action $format = $controller->format; switch ($format) { default: case 'html': header('Content-Type: text/html; encoding=utf-8'); $view = $controller->controller . '/' . $controller->action; if (!empty($controller->module)) { $view = $controller->module . '/' . $view; } $path = $view . '.phtml'; break; case 'json': header('Content-Type: application/json; encoding=utf-8'); echo json_encode($result); break; case 'txt': header('Content-Type: text/plain; encoding=utf-8'); echo serialize($result); break; case 'xml': header('Content-Type: text/xml; encoding=utf-8'); $doc = new \DOMDocument('1.0', 'UTF-8'); $doc->formatOutput = true; $addNode = function (\DOMNode $node, $name, $value, $self) use($doc) { $type = gettype($value); $el = $doc->createElement($name); $typeAttr = $doc->createAttribute('type'); $typeAttr->value = $type; $el->appendChild($typeAttr); switch (strtolower($type)) { case 'null': $el->textContent = 'null'; break; case 'string': case 'int': case 'double': $el->textContent = (string) $value; break; case 'boolean': $el->textContent = $value ? 'true' : 'false'; break; case 'object': if ($value instanceof XmlSerializable) { $value = $value->xmlSerialize(); } else { $value = (array) $value; } case 'array': foreach ($value as $key => $val) { $self($el, $key, $val, $self); } break; case 'resource': $el->textContent = get_resource_type($value); break; } }; $addNode($doc, 'value', $result, $addNode); echo $doc->saveXML(); break; } }
public static function fromString($string) { $parts = StringUtil::mapReverse($string, ':', ['password', 'userName']); return new static($parts['userName'], $parts['password']); }
/** * Interpolates {{var.subVar}}-style based on a source array given * * Dimensions in the source array are accessed with a passed delimeter (Default: Dot (.)) * * @param string $string The input string to operate on * @param array $source The associative source array * @param mixed $defaultValue The default value for indices that dont exist * @param string|null $delimeter The delimeter for multi-dimension access (Default: Dot (.)) * * @return string The interpolated string with the variables replaced with their values */ public static function interpolate($string, array $source, $defaultValue = null, $delimeter = null) { return preg_replace_callback('/\\{\\{([^\\}]+)\\}\\}/i', function ($m) use($source, $defaultValue, $delimeter) { $resolved = StringUtil::resolve($m[1], $source, $defaultValue, $delimeter); if ($resolved === null) { return $m[0]; } return $resolved; }, $string); }
public function init() { $this->prependOptions(['defaultController' => 'index', 'defaultAction' => 'index', 'defaultId' => null, 'defaultFormat' => 'html', 'formats' => ['html', 'json'], 'routeOnRun' => true, 'baseUrl' => null, 'routes' => ['/:controller?/:action?/:id?.:format?' => ["@router", 'dispatchController']]]); $app = $this->getApp(); $app->bind('beforeRun', function () { $routes = $this->getOption('routes'); //Parse route targets foreach ($routes as $route => $callback) { if (is_array($callback) && is_string($callback[0])) { $target = $callback[0]; if ($target[0] !== '@') { break; } $handler = $callback[1]; $target = substr($target, 1); switch ($target) { case 'router': $routes[$route][0] = $this; break; default: $routes[$route] = function (array $routeData) use($target, $handler) { $routeData = call_user_func([$target, $handler], $routeData); return $this->dispatchController($routeData); }; } } } if (isset($this->controller)) { /** * @var \Tale\App\Feature\Controller $controller */ $controller = $this->controller; $controller->registerHelper('getUrl', function ($controller, $path = null, array $args = null, $preserveQuery = false) { $path = $path ? $path : ''; if (isset($controller->request)) { /** * @var \Tale\App\Feature\Controller\Request $req */ $req = $controller->request; $path = StringUtil::interpolate($path, ['controller' => $req->getController(), 'action' => $req->getAction(), 'args' => $req->getArgs(), 'format' => $req->getFormat()]); } $url = $path; $baseUrl = $this->getOption('baseUrl'); if ($baseUrl) { $url = rtrim($baseUrl, '/') . '/' . ltrim($path, '/'); } $query = []; if ($args) { $query = $args; } if ($preserveQuery && isset($controller->webRequest)) { $query = array_replace_recursive($controller->webRequest->getUrlArgs(), $query); } if (!empty($query)) { $url .= '?' . http_build_query($query); } return $url; }); $controller->registerHelper('redirect', function ($controller, $path, array $args = null, $preserveQuery = null) { return new Controller\Response\Redirect($controller->getUrl($path, $args, $preserveQuery)); }); } $this->_router = new AppRouter($routes); }); $app->bind('run', function () use($app) { if ($this->getOption('routeOnRun')) { if ($app->isCliApp()) { $this->routeCliRequest(); } else { $response = $this->routeHttpServerRequest(); $response->apply(); } } }); $app->bind('afterRun', function () { unset($this->_router); }); }
public static function getHeadersFromEnvironment() { self::_validateWebEnvironment(); foreach ($_SERVER as $name => $value) { if (strncmp($name, 'HTTP_', 5) === 0) { $name = StringUtil::dasherize(StringUtil::humanize(strtolower(substr($name, 5)))); (yield $name => $value); } } }
public function renderView($path, array $args = null, $cacheHtml = false) { $renderView = function () use($path, $args) { $phtml = $this->fetchCached('views.' . StringUtil::canonicalize($path), function () use($path) { return $this->getConvertedContent(self::TYPE_VIEW, $path); }, $this->getOption('lifeTime')); if (!$phtml) { throw new \Exception("Failed to convert theme: Neither {$path} nor" . " any convertible file could be found"); } $dataUri = "{$this->_wrapperName}://data;{$phtml}"; $render = function ($__dataUri, $__args) { ob_start(); extract($__args); include $__dataUri; return ob_get_clean(); }; return $render($dataUri, $args ? $args : []); }; if (!$cacheHtml) { return $renderView(); } return $this->fetchCached('views.html.' . StringUtil::canonicalize($path), $renderView, $this->getOption('lifeTime')); }
public function __call($method, array $args = null) { if (!strlen($method) < 4) { $args = $args ? $args : []; $token = substr($method, 0, 3); if (in_array($token, ['has', 'get', 'set', 'add'])) { $name = substr($method, 3); $suffix = ''; if (strlen($name) > 5 && substr($name, -5) === 'Array') { $name = substr($name, 0, -5); $suffix = 'Array'; } $plural = StringUtil::pluralize($name); $singular = $plural !== $name; $table = $this->getDatabase()->{$plural}; array_unshift($args, $table); switch (substr($method, 0, 3)) { case 'has': if ($singular) { return call_user_func_array([$this, 'countOne'], $args) ? true : false; } return call_user_func_array([$this, 'countMany'], $args) ? true : false; case 'get': if ($singular) { return call_user_func_array([$this, 'selectOne'], $args); } return call_user_func_array([$this, 'selectMany'], $args); case 'set': if ($singular) { return call_user_func_array([$this, 'setOne'], $args); } return call_user_func_array([$this, 'setMany' . $suffix], $args); case 'add': if ($singular) { return call_user_func_array([$this, 'addManyOne'], $args); } throw new Exception("Failed to add {$table}: No plural action available"); } } if (strlen($method) > 5) { $token = substr($method, 0, 5); if (in_array($token, ['count'])) { $name = substr($method, 5); $plural = StringUtil::pluralize($name); $singular = $plural !== $name; $table = $this->getDatabase()->{$plural}; array_unshift($args, $table); if ($singular) { return call_user_func_array([$this, 'countOne'], $args); } return call_user_func_array([$this, 'countMany'], $args); } } } throw new BadMethodCallException("Failed to call method {$method}: Method doesnt exist"); }
public static function fromString($uriString) { return new static(StringUtil::map($uriString, ':', ['scheme', 'path'])); }
public function getModelClassName() { $nameSpaces = $this->_database->getModelNameSpaces(); if (empty($nameSpaces)) { return null; } foreach ($nameSpaces as $nameSpace) { $className = rtrim($nameSpace, '\\') . '\\' . StringUtil::camelize(StringUtil::singularize($this->getName())); if (!class_exists($className)) { continue; } if (!is_subclass_of($className, 'Tale\\Data\\Row')) { throw new \Exception("Failed to use {$className} as a model class: " . "The class needs to extend Tale\\Data\\Row"); } return $className; } return null; }