Inheritance: extends Prefab
Esempio n. 1
0
 /**
  * Encode the input parameter $data as JSON and output it with appropriate http headers.
  *
  * @param mixed $data   input variable, takes origin, age, methods
  * @param array $params parameters for the http headers: ttl, origin, methods (GET, POST, PUT, DELETE)
  * @param bool  $output send the output headers and body? or return them?
  *
  * @return array (array headers, string body)
  *
  * @see http://www.w3.org/TR/2008/WD-access-control-20080912/
  */
 public static function json(array $data, array $params = [], bool $output = true)
 {
     $f3 = \Base::instance();
     $headers = array_key_exists('headers', $params) ? $params['headers'] : [];
     $headers['Content-type'] = 'application/json; charset=utf-8';
     $ttl = array_key_exists('ttl', $params) ? $params['ttl'] : 0;
     // cache for $ttl seconds
     if (empty($ttl)) {
         $f3->expire(0);
         //$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
         $ttl = 0;
     }
     $headers['Expires'] = Time::http(array_key_exists('expires', $params) ? $params['expires'] : time() + $ttl);
     $headers['Access-Control-Max-Age'] = $ttl;
     $headers['Access-Control-Allow-Methods'] = array_key_exists('http_methods', $params) ? $params['http_methods'] : '';
     //'OPTIONS, HEAD, GET, POST, PUT, PATCH, DELETE';
     $headers['Access-Control-Allow-Origin'] = array_key_exists('acl_origin', $params) ? $params['acl_origin'] : '*';
     $headers['Access-Control-Allow-Credentials'] = array_key_exists('acl_credentials', $params) ? $params['credentials'] : 'false';
     $body = json_encode($data, JSON_PRETTY_PRINT);
     if (!empty($output)) {
         $headers['Content-Length'] = \UTF::instance()->strlen($body);
     }
     $headers['ETag'] = array_key_exists('etag', $params) ? $params['etag'] : md5($body);
     if (empty($output)) {
         return ['headers' => $headers, 'body' => $body];
     } else {
         // send the headers + data
         foreach ($headers as $header => $value) {
             if (is_string($value) && empty($value)) {
                 continue;
             }
             header($header . ': ' . $value);
         }
         if (!array_key_exists('cookie', $params)) {
             header_remove('Set-Cookie');
             // prevent php session
         }
         // default status is 200 - OK
         $f3->status(array_key_exists('http_status', $params) ? $params['http_status'] : 200);
         $method = $f3->get('VERB');
         switch ($method) {
             case 'HEAD':
                 break;
             default:
             case 'GET':
             case 'PUT':
             case 'POST':
             case 'DELETE':
                 echo $body;
         }
     }
 }
Esempio n. 2
0
 /**
  * generate random string
  *
  * @param int $length of password
  * @param string $chars characters to use for random string
  * @return string password
  */
 public static function random(int $length = 10, string $chars = null) : string
 {
     if (empty($chars)) {
         // ignore characters which can be consued, i, l, 1, o, O, 0 etc
         $chars = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWYZ';
     }
     $chars = str_shuffle($chars);
     // shuffle base character string
     $x = \UTF::instance()->strlen($chars) - 1;
     $str = '';
     for ($i = 0; $i < $length; $i++) {
         $str .= \UTF::instance()->substr($chars, rand(0, $x), 1);
     }
     return (string) $str;
 }
Esempio n. 3
0
 /**
  * Utility to convert timestamp into a http header date/time.
  *
  * @param int time php time value
  * @param string $zone timezone
  */
 public static function HTTP(int $unixtime = null, string $zone = '') : string
 {
     $f3 = \Base::instance();
     // use current time if bad time value or unset
     $unixtime = (int) $unixtime;
     if (0 >= $unixtime) {
         $unixtime = time();
     }
     // if its not a 3 letter timezone set it to GMT
     if (3 == \UTF::instance()->strlen($zone)) {
         $zone = strtoupper($zone);
     } else {
         $zone = '';
     }
     return \UTF::instance()->trim(gmdate('D, d M Y H:i:s', $unixtime) . ' ' . $zone);
 }
Esempio n. 4
0
 /**
  * Return an f3 URL route by its alias or the given path
  * converting 2nd argument $params to querystring if array
  *
  * @param string $url name of the url alias if beginning with @ or relative
  * 
  * @param mixed $params url params as string or array
  * @param boolean $full default true
  * @return string
  */
 public static function internal(string $url, $params = null, bool $full = true) : string
 {
     $f3 = \Base::instance();
     if ('@' == $url[0]) {
         $url = $f3->alias(\UTF::instance()->substr($url, 1));
     }
     // missing slash at start of url path
     if ('/' !== \UTF::instance()->substr($url, 0, 1)) {
         $url = '/' . $url;
     }
     if (!empty($params)) {
         $session_name = strtolower(session_name());
         if (array_key_exists($session_name, $params)) {
             unset($params[$session_name]);
         }
         if (is_array($params)) {
             $params = http_build_query($params);
         }
         if (!empty($params)) {
             $url .= '?' . $params;
         }
     }
     return empty($full) ? $url : $f3->get('SCHEME') . '://' . $f3->get('HOST') . $url;
 }
Esempio n. 5
0
 /**
  * Bind value to key
  * @return mixed
  * @param $key string
  * @param $val mixed
  */
 function set($key, $val)
 {
     $fields = $this->fieldConf;
     unset($this->fieldsCache[$key]);
     // pre-process if field config available
     if (!empty($fields) && isset($fields[$key]) && is_array($fields[$key])) {
         // handle relations
         if (isset($fields[$key]['belongs-to-one'])) {
             // one-to-many, one-to-one
             if (is_null($val)) {
                 $val = NULL;
             } elseif (is_object($val) && !($this->dbsType == 'mongo' && $val instanceof \MongoId)) {
                 // fetch fkey from mapper
                 if (!$val instanceof Cortex || $val->dry()) {
                     trigger_error(self::E_INVALID_RELATION_OBJECT);
                 } else {
                     $relConf = $fields[$key]['belongs-to-one'];
                     $rel_field = is_array($relConf) ? $relConf[1] : '_id';
                     $val = $val->get($rel_field, true);
                 }
             } elseif ($this->dbsType == 'mongo' && !$val instanceof \MongoId) {
                 $val = new \MongoId($val);
             }
         } elseif (isset($fields[$key]['has-one'])) {
             $relConf = $fields[$key]['has-one'];
             if (is_null($val)) {
                 $val = $this->get($key);
                 $val->set($relConf[1], NULL);
             } else {
                 if (!$val instanceof Cortex) {
                     $rel = $this->getRelInstance($relConf[0], null, $key);
                     $rel->load(array('_id = ?', $val));
                     $val = $rel;
                 }
                 $val->set($relConf[1], $this->_id);
             }
             $this->saveCsd[$key] = $val;
             return $val;
         } elseif (isset($fields[$key]['belongs-to-many'])) {
             // many-to-many, unidirectional
             $fields[$key]['type'] = self::DT_JSON;
             $relConf = $fields[$key]['belongs-to-many'];
             $rel_field = is_array($relConf) ? $relConf[1] : '_id';
             $val = $this->getForeignKeysArray($val, $rel_field, $key);
         } elseif (isset($fields[$key]['has-many'])) {
             // many-to-many, bidirectional
             $relConf = $fields[$key]['has-many'];
             if ($relConf['hasRel'] == 'has-many') {
                 // custom setter
                 $val = $this->emit('set_' . $key, $val);
                 $val = $this->getForeignKeysArray($val, '_id', $key);
                 $this->saveCsd[$key] = $val;
                 // array of keys
                 return $val;
             } elseif ($relConf['hasRel'] == 'belongs-to-one') {
                 // TODO: many-to-one, bidirectional, inverse way
                 trigger_error("not implemented");
             }
         }
         // convert array content
         if (is_array($val) && $this->dbsType == 'sql') {
             if ($fields[$key]['type'] == self::DT_SERIALIZED) {
                 $val = serialize($val);
             } elseif ($fields[$key]['type'] == self::DT_JSON) {
                 $val = json_encode($val);
             } else {
                 trigger_error(sprintf(self::E_ARRAY_DATATYPE, $key));
             }
         }
         // add nullable polyfill
         if ($val === NULL && ($this->dbsType == 'jig' || $this->dbsType == 'mongo') && array_key_exists('nullable', $fields[$key]) && $fields[$key]['nullable'] === false) {
             trigger_error(sprintf(self::E_NULLABLE_COLLISION, $key));
         }
         // MongoId shorthand
         if ($this->dbsType == 'mongo' && !$val instanceof \MongoId) {
             if ($key == '_id') {
                 $val = new \MongoId($val);
             } elseif (preg_match('/INT/i', $fields[$key]['type']) && !isset($fields[$key]['relType'])) {
                 $val = (int) $val;
             }
         }
         if (preg_match('/BOOL/i', $fields[$key]['type'])) {
             $val = !$val || $val === 'false' ? false : (bool) $val;
             if ($this->dbsType == 'sql') {
                 $val = (int) $val;
             }
         }
     }
     // fluid SQL
     if ($this->fluid && $this->dbsType == 'sql') {
         $schema = new Schema($this->db);
         $table = $schema->alterTable($this->table);
         // add missing field
         if (!in_array($key, $table->getCols())) {
             // determine data type
             if (isset($this->fieldConf[$key]) && isset($this->fieldConf[$key]['type'])) {
                 $type = $this->fieldConf[$key]['type'];
             } elseif (is_int($val)) {
                 $type = $schema::DT_INT;
             } elseif (is_double($val)) {
                 $type = $schema::DT_DOUBLE;
             } elseif (is_float($val)) {
                 $type = $schema::DT_FLOAT;
             } elseif (is_bool($val)) {
                 $type = $schema::DT_BOOLEAN;
             } elseif (date('Y-m-d H:i:s', strtotime($val)) == $val) {
                 $type = $schema::DT_DATETIME;
             } elseif (date('Y-m-d', strtotime($val)) == $val) {
                 $type = $schema::DT_DATE;
             } elseif (\UTF::instance()->strlen($val) <= 255) {
                 $type = $schema::DT_VARCHAR256;
             } else {
                 $type = $schema::DT_TEXT;
             }
             $table->addColumn($key)->type($type);
             $table->build();
             // update mapper fields
             $newField = $table->getCols(true);
             $newField = $newField[$key];
             $refl = new \ReflectionObject($this->mapper);
             $prop = $refl->getProperty('fields');
             $prop->setAccessible(true);
             $fields = $prop->getValue($this->mapper);
             $fields[$key] = $newField + array('value' => NULL, 'changed' => NULL);
             $prop->setValue($this->mapper, $fields);
         }
     }
     // custom setter
     $val = $this->emit('set_' . $key, $val);
     return $this->mapper->set($key, $val);
 }
Esempio n. 6
0
 /**
  * setup the base application environment.
  *
  * @param \Base $f3
  * @return void
  */
 public static function start()
 {
     $f3 = \Base::instance();
     // http://php.net/manual/en/function.ob-start.php
     ob_start();
     // read config and overrides
     // @see http://fatfreeframework.com/framework-variables#configuration-files
     $f3->config('config/default.ini');
     // by default this file does not exist, you must create it and include your local settings
     if (file_exists('config/config.ini')) {
         $f3->config('config/config.ini');
     }
     // set home directory for project
     $f3->set('HOMEDIR', realpath($f3->get('SERVER.DOCUMENT_ROOT') . '/../'));
     // make sure directories are full, not relative path
     foreach (['LOGS', 'TEMP', 'UPLOADS'] as $key) {
         $dir = $f3->get($key);
         if (!empty($dir)) {
             $dir = realpath($dir);
             $f3->set($key, $dir . '/');
         }
     }
     // these take multiple paths
     $language = $f3->get('LANGUAGE');
     foreach (['LOCALES', 'UI'] as $key) {
         $paths = $f3->get($key);
         // remove any invalid dirs
         if (!empty($paths)) {
             $dirs = $f3->split($paths);
             foreach ($dirs as $k => $dir) {
                 if (empty($dir)) {
                     unset($dirs[$k]);
                     continue;
                 }
                 // switch for different language templates
                 $langDir = '';
                 if ('UI' == $key) {
                     $langDir = 'templates/' . $language . '/' . $dir;
                     $dir = 'templates/en/' . $dir;
                     if (!file_exists($langDir)) {
                         unset($langDir);
                     }
                 }
                 if (!empty($langDir)) {
                     $dirs[$k] = realpath($langDir) . '/' . ';' . realpath($dir) . '/';
                 } else {
                     $dirs[$k] = realpath($dir) . '/';
                 }
             }
             $f3->set($key, join(';', $dirs));
         }
     }
     $debug = $f3->get('debug');
     // default cacheable data time in seconds from config
     $ttl = $f3->get('ttl.default');
     // enable full logging if not production
     $logfile = $f3->get('log.file');
     if (empty($logfile)) {
         $f3->set('log.file', '/dev/null');
     } elseif ('production' !== $f3->get('app.env')) {
         ini_set('log_errors', 'On');
         $logfile = $f3->get('LOGS') . $logfile;
         $f3->set('logfile', $logfile);
         ini_set('error_log', $logfile);
         ini_set('error_reporting', -1);
         ini_set('ignore_repeated_errors', 'On');
         ini_set('ignore_repeated_source', 'On');
     }
     // parse params for http-style dsn
     // setup database connection params
     // @see http://fatfreeframework.com/databases
     $httpDSN = $f3->get('db.dsn_http');
     if (!empty($httpDSN)) {
         $dbParams = $f3->get('db');
         $params = \FFMVC\Helpers\DB::instance()->parseHttpDsn($httpDSN);
         $params['dsn'] = \FFMVC\Helpers\DB::instance()->createDbDsn($params);
         $dbParams = array_merge($dbParams, $params);
         $f3->set('db', $dbParams);
     }
     // setup outgoing email server for php mail command
     ini_set('SMTP', $f3->get('email.host'));
     ini_set('sendmail_from', $f3->get('email.from'));
     ini_set('smtp_port', $f3->get('email.port'));
     ini_set('user', $f3->get('email.user'));
     ini_set('password', $f3->get('email.pass'));
     if (PHP_SAPI !== 'cli') {
         return;
     }
     // log errors if run on command line
     ini_set('display_errors', 'On');
     ini_set('error_log', 'On');
     ini_set('html_errors', 'Off');
     // set default error handler output for CLI mode
     $f3->set('ONERROR', function ($f3) {
         $e = $f3->get('ERROR');
         // detailed error notifications because it's not public
         $errorMessage = sprintf("Trace: %s\n\nException %d: %s\n%s\n", $e['trace'], $e['code'], $e['status'], $e['text']);
         echo $errorMessage;
         if (\Registry::exists('logger')) {
             $logger = \Registry::get('logger');
             if (is_object($logger)) {
                 $logger->write($errorMessage, $f3->get('log.date'));
             }
         }
     });
     // fix for f3 not populating $_GET when run on the command line
     $uri = $f3->get('SERVER.REQUEST_URI');
     $querystring = preg_split("/&/", \UTF::instance()->substr($uri, 1 + \UTF::instance()->strpos($uri . '&', '?')));
     if (!empty($querystring) && count($querystring)) {
         foreach ($querystring as $pair) {
             if (0 == count($pair)) {
                 continue;
             }
             $val = preg_split("/=/", $pair);
             if (!empty($val) && count($val) == 2) {
                 $k = $val[0];
                 $v = $val[1];
                 if (!empty($k) && !empty($v)) {
                     $_GET[$k] = $v;
                 }
             }
         }
         $f3->set('GET', $_GET);
     }
 }
Esempio n. 7
0
 function Unicode()
 {
     $this->set('title', 'Unicode');
     $str = 'אני יכול לאכול זכוכית וזה לא מזיק לי';
     $this->expect(is_null($this->get('ERROR')), 'No errors expected at this point', 'ERROR variable is set: ' . $this->get('ERROR.text'));
     $this->expect(UTF::strlen($str) == 36, 'String length evaluated correctly', 'String length is wrong: ' . UTF::strlen($str));
     $this->expect(UTF::substr($str, 0, 5) == 'אני י', 'Substring at offset 0 (length 5) is correct', 'Substring at offset 0 (length 5) is wrong: ' . UTF::substr($str, 0, 5));
     $this->expect(UTF::substr($str, 12) == 'ול זכוכית וזה לא מזיק לי', 'Substring at offset 12 (unspecified length) is correct', 'Substring at offset 12 (unspecified length) is wrong: ' . UTF::substr($str, 12));
     $this->expect(UTF::substr($str, 3, 4) == ' יכו', 'Substring at offset 3 (length 4) is correct', 'Substring at offset 3 (length 4) is wrong: ' . UTF::substr($str, 3, 4));
     $this->expect(UTF::substr('', 7) == FALSE, 'Substring of empty string returns FALSE', 'Substring of empty string returns non-boolean value: ' . UTF::substr('', 0));
     $this->expect(UTF::substr($str, -5) == 'יק לי', 'Substring at negative offset is correct', 'Substring at negative offset is wrong: ' . UTF::substr($str, -5));
     $this->expect(UTF::strpos($str, 'ת וזה') == 20, 'String position detected accurately', 'String position detected incorrectly');
     $this->expect(UTF::strpos($str, 'xyz') === FALSE, 'Non-existent substring returns FALSE', 'Non-existent substring returns non-boolean value: ' . UTF::strpos($str, 'xyz'));
     $this->expect(UTF::strrpos($str, 'כ') == 18, 'String position (right-to-left) detected accurately', 'String position (right-to-left) detected incorrectly');
     $this->expect(UTF::strstr($str, 'לא מ', TRUE) == 'אני יכול לאכול זכוכית וזה ', 'Substring search returns correct value', 'Substring search failed: ' . UTF::strstr($str, 'לא מ', TRUE));
     $this->expect(UTF::strstr($str, 'לא מזי') == 'לא מזיק לי', 'Substring search returns correct latent value', 'Substring search failed: ' . UTF::strstr($str, 'לא מ'));
     $this->expect(UTF::substr_count($str, 'כו') == 3, 'Substring count is correct', 'Substring count is incorrect');
     echo $this->render('basic/results.htm');
 }
Esempio n. 8
0
 /**
  * Translate emoji tokens to Unicode font-supported symbols
  *
  * The callback function receives two arguments:
  * The value to filter, and any parameters used in the filter rule. It should returned the filtered value.
  *
  * @param $value
  * @param array $param
  *
  * @return type
  * @link https://fatfreeframework.com/utf-unicode-string-manager#emojify
  */
 public function filter_emojify($value, $param = null)
 {
     return \UTF::instance()->emojify($value);
 }