Nette-2.4-20160731/ 0000755 0000000 0000000 00000000000 12747434646 012056 5 ustar root root Nette-2.4-20160731/version.txt 0000644 0000000 0000000 00000002437 12747434606 014306 0 ustar root root Nette 2.4-20160731
latte/latte v2.4.1 Latte: the amazing template engine for PHP
nette/application v2.4.1 Nette Application MVC Component
nette/bootstrap v2.4.1 Nette Bootstrap
nette/caching v2.5.1 Nette Caching Component
nette/component-model v2.3.0 Nette Component Model
nette/database v2.4.0 Nette Database Component
nette/deprecated v2.4.0 APIs and features removed from Nette Framework
nette/di v2.4.2 Nette Dependency Injection Component
nette/finder v2.4.0 Nette Finder: Files Searching
nette/forms v2.4.1 Nette Forms: greatly facilitates web forms
nette/http v2.4.0 Nette HTTP Component
nette/mail v2.4.1 Nette Mail: Sending E-mails
nette/neon v2.4.0 Nette NEON: parser & generator for Nette Object Notation
nette/php-generator v2.4.1 Nette PHP Generator
nette/reflection v2.4.0 Nette PHP Reflection Component
nette/robot-loader v2.4.0 Nette RobotLoader: comfortable autoloading
nette/safe-stream v2.3.2 Nette SafeStream: Atomic Operations
nette/security v2.4.0 Nette Security: Access Control Component
nette/tokenizer v2.2.3 Nette Tokenizer
nette/utils v2.4.0 Nette Utility Classes
tracy/tracy v2.4.2 Tracy: useful PHP debugger
Nette-2.4-20160731/tools/ 0000755 0000000 0000000 00000000000 12747434604 013210 5 ustar root root Nette-2.4-20160731/tools/open-in-editor/ 0000755 0000000 0000000 00000000000 12747434604 016041 5 ustar root root Nette-2.4-20160731/tools/open-in-editor/open-editor.js 0000644 0000000 0000000 00000002724 12747434604 020631 0 ustar root root // NetBeans
// var editor = '"C:\\Program Files\\NetBeans 8.1\\bin\\netbeans.exe" "%file%:%line%" --console suppress';
// PhpStorm
// var editor = '"C:\\Program Files (x86)\\JetBrains\\PhpStorm 10.0\\bin\\PhpStorm.exe" --line %line% "%file%"';
// Nusphere PHPEd
// var editor = '"C:\\Program Files\\NuSphere\\PhpED\\phped.exe" "%file%" --line=%line%';
// SciTE
// var editor = '"C:\\Program Files\\SciTE\\scite.exe" "-open:%file%" -goto:%line%';
// EmEditor
// var editor = '"C:\\Program Files\\EmEditor\\EmEditor.exe" "%file%" /l %line%';
// PSPad Editor
// var editor = '"C:\\Program Files\\PSPad editor\\PSPad.exe" -%line% "%file%"';
// gVim
// var editor = '"C:\\Program Files\\Vim\\vim73\\gvim.exe" "%file%" +%line%';
// Sublime Text 2
// var editor = '"C:\\Program Files\\Sublime Text 2\\sublime_text.exe" "%file%:%line%"';
var mappings = {
// '/remotepath': '/localpath'
};
if (typeof editor === 'undefined') {
WScript.Echo('Create variable "editor" in ' + WScript.ScriptFullName);
WScript.Quit();
}
var url = WScript.Arguments(0);
var match = /^editor:\/\/open\/\?file=(.+)&line=(\d+)/.exec(url);
if (match) {
var file = decodeURIComponent(match[1]).replace(/\+/g, ' ');
for (var id in mappings) {
if (file.indexOf(id) === 0) {
file = mappings[id] + file.substr(id.length);
break;
}
}
var command = editor.replace(/%line%/g, match[2]).replace(/%file%/g, file);
var shell = new ActiveXObject("WScript.Shell");
shell.Exec(command.replace(/\\/g, '\\\\'));
}
Nette-2.4-20160731/tools/open-in-editor/install.cmd 0000644 0000000 0000000 00000000601 12747434604 020171 0 ustar root root @echo off
:: This Windows batch file sets open-editor.js as handler for editor:// protocol
if defined PROCESSOR_ARCHITEW6432 (set reg="%systemroot%\sysnative\reg.exe") else (set reg=reg)
%reg% ADD HKCR\editor /ve /d "URL:editor Protocol" /f
%reg% ADD HKCR\editor /v "URL Protocol" /d "" /f
%reg% ADD HKCR\editor\shell\open\command /ve /d "wscript \"%~dp0open-editor.js\" \"%%1\"" /f
Nette-2.4-20160731/readme.txt 0000644 0000000 0000000 00000005067 12747434552 014060 0 ustar root root [Nette Framework](https://nette.org)
===================================
[](https://packagist.org/packages/nette/nette)
[](https://github.com/nette/nette/releases)
[](https://github.com/nette/nette/blob/master/license.md)
[](https://gitter.im/nette/nette)
Nette Framework is a popular tool for PHP web development. It is designed to be
as usable and as friendly as possible. It focuses on security and
performance and is definitely one of the safest PHP frameworks.
Nette Framework speaks your language and helps you to easily build better websites.
It contains these packages:
- [Application](https://github.com/nette/application)
- [Bootstrap](https://github.com/nette/bootstrap)
- [Caching](https://github.com/nette/caching)
- [Component Model](https://github.com/nette/component-model)
- [Database](https://github.com/nette/database)
- [DI](https://github.com/nette/di)
- [Finder](https://github.com/nette/finder)
- [Forms](https://github.com/nette/forms)
- [Http](https://github.com/nette/http)
- [Mail](https://github.com/nette/mail)
- [Neon](https://github.com/nette/neon)
- [Php Generator](https://github.com/nette/php-generator)
- [Reflection](https://github.com/nette/reflection)
- [Robot Loader](https://github.com/nette/robot-loader)
- [Safe Stream](https://github.com/nette/safe-stream)
- [Security](https://github.com/nette/security)
- [Tokenizer](https://github.com/nette/tokenizer)
- [Utils](https://github.com/nette/utils)
- [Latte](https://latte.nette.org)
- [Tracy](https://tracy.nette.org)
- [deprecated](https://github.com/nette/deprecated)
- and [Tester](https://tester.nette.org)
Installation
------------
The best way to install Nette Framework is to download the latest package
from https://nette.org/download or use [Composer](https://doc.nette.org/composer).
All Nette components are 100% compatible with PHP 7. Minimal required version of
PHP is 5.6.0 for Nette Framework 2.4-dev and PHP 5.3.1 for stable Nette Framework 2.3.
Please run [Requirements Checker](https://doc.nette.org/requirements) to obtain more detailed information.
Getting started
---------------
The [Quick Start tutorial](https://doc.nette.org/quickstart) gives you a first
introduction to the framework by creating a simple database driven application.
Nette-2.4-20160731/Nette/ 0000755 0000000 0000000 00000000000 12747434622 013127 5 ustar root root Nette-2.4-20160731/Nette/Utils/ 0000755 0000000 0000000 00000000000 12747434604 014227 5 ustar root root Nette-2.4-20160731/Nette/Utils/Validators.php 0000644 0000000 0000000 00000016572 12747434604 017063 0 ustar root root 'is_bool',
'boolean' => 'is_bool',
'int' => 'is_int',
'integer' => 'is_int',
'float' => 'is_float',
'number' => NULL, // is_int || is_float,
'numeric' => [__CLASS__, 'isNumeric'],
'numericint' => [__CLASS__, 'isNumericInt'],
'string' => 'is_string',
'unicode' => [__CLASS__, 'isUnicode'],
'array' => 'is_array',
'list' => [Arrays::class, 'isList'],
'object' => 'is_object',
'resource' => 'is_resource',
'scalar' => 'is_scalar',
'callable' => [__CLASS__, 'isCallable'],
'null' => 'is_null',
'email' => [__CLASS__, 'isEmail'],
'url' => [__CLASS__, 'isUrl'],
'uri' => [__CLASS__, 'isUri'],
'none' => [__CLASS__, 'isNone'],
'type' => [__CLASS__, 'isType'],
'identifier' => [__CLASS__, 'isPhpIdentifier'],
'pattern' => NULL,
'alnum' => 'ctype_alnum',
'alpha' => 'ctype_alpha',
'digit' => 'ctype_digit',
'lower' => 'ctype_lower',
'upper' => 'ctype_upper',
'space' => 'ctype_space',
'xdigit' => 'ctype_xdigit',
];
protected static $counters = [
'string' => 'strlen',
'unicode' => [Strings::class, 'length'],
'array' => 'count',
'list' => 'count',
'alnum' => 'strlen',
'alpha' => 'strlen',
'digit' => 'strlen',
'lower' => 'strlen',
'space' => 'strlen',
'upper' => 'strlen',
'xdigit' => 'strlen',
];
/**
* Throws exception if a variable is of unexpected type.
* @param mixed
* @param string expected types separated by pipe
* @param string label
* @return void
*/
public static function assert($value, $expected, $label = 'variable')
{
if (!static::is($value, $expected)) {
$expected = str_replace(['|', ':'], [' or ', ' in range '], $expected);
if (is_array($value)) {
$type = 'array(' . count($value) . ')';
} elseif (is_object($value)) {
$type = 'object ' . get_class($value);
} elseif (is_string($value) && strlen($value) < 40) {
$type = "string '$value'";
} else {
$type = gettype($value);
}
throw new AssertionException("The $label expects to be $expected, $type given.");
}
}
/**
* Throws exception if an array field is missing or of unexpected type.
* @param array
* @param string item
* @param string expected types separated by pipe
* @param string
* @return void
*/
public static function assertField($arr, $field, $expected = NULL, $label = "item '%' in array")
{
self::assert($arr, 'array', 'first argument');
if (!array_key_exists($field, $arr)) {
throw new AssertionException('Missing ' . str_replace('%', $field, $label) . '.');
} elseif ($expected) {
static::assert($arr[$field], $expected, str_replace('%', $field, $label));
}
}
/**
* Finds whether a variable is of expected type.
* @param mixed
* @param string expected types separated by pipe with optional ranges
* @return bool
*/
public static function is($value, $expected)
{
foreach (explode('|', $expected) as $item) {
list($type) = $item = explode(':', $item, 2);
if (isset(static::$validators[$type])) {
if (!call_user_func(static::$validators[$type], $value)) {
continue;
}
} elseif ($type === 'number') {
if (!is_int($value) && !is_float($value)) {
continue;
}
} elseif ($type === 'pattern') {
if (preg_match('|^' . (isset($item[1]) ? $item[1] : '') . '\z|', $value)) {
return TRUE;
}
continue;
} elseif (!$value instanceof $type) {
continue;
}
if (isset($item[1])) {
$length = $value;
if (isset(static::$counters[$type])) {
$length = call_user_func(static::$counters[$type], $value);
}
$range = explode('..', $item[1]);
if (!isset($range[1])) {
$range[1] = $range[0];
}
if (($range[0] !== '' && $length < $range[0]) || ($range[1] !== '' && $length > $range[1])) {
continue;
}
}
return TRUE;
}
return FALSE;
}
/**
* Finds whether a value is an integer.
* @return bool
*/
public static function isNumericInt($value)
{
return is_int($value) || is_string($value) && preg_match('#^-?[0-9]+\z#', $value);
}
/**
* Finds whether a string is a floating point number in decimal base.
* @return bool
*/
public static function isNumeric($value)
{
return is_float($value) || is_int($value) || is_string($value) && preg_match('#^-?[0-9]*[.]?[0-9]+\z#', $value);
}
/**
* Finds whether a value is a syntactically correct callback.
* @return bool
*/
public static function isCallable($value)
{
return $value && is_callable($value, TRUE);
}
/**
* Finds whether a value is an UTF-8 encoded string.
* @param string
* @return bool
*/
public static function isUnicode($value)
{
return is_string($value) && preg_match('##u', $value);
}
/**
* Finds whether a value is "falsy".
* @return bool
*/
public static function isNone($value)
{
return $value == NULL; // intentionally ==
}
/**
* Finds whether a variable is a zero-based integer indexed array.
* @param array
* @return bool
*/
public static function isList($value)
{
return Arrays::isList($value);
}
/**
* Is a value in specified range?
* @param mixed
* @param array min and max value pair
* @return bool
*/
public static function isInRange($value, $range)
{
return (!isset($range[0]) || $range[0] === '' || $value >= $range[0])
&& (!isset($range[1]) || $range[1] === '' || $value <= $range[1]);
}
/**
* Finds whether a string is a valid email address.
* @param string
* @return bool
*/
public static function isEmail($value)
{
$atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part
$alpha = "a-z\x80-\xFF"; // superset of IDN
return (bool) preg_match("(^
(\"([ !#-[\\]-~]*|\\\\[ -~])+\"|$atom+(\\.$atom+)*) # quoted or unquoted
@
([0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)+ # domain - RFC 1034
[$alpha]([-0-9$alpha]{0,17}[$alpha])? # top domain
\\z)ix", $value);
}
/**
* Finds whether a string is a valid http(s) URL.
* @param string
* @return bool
*/
public static function isUrl($value)
{
$alpha = "a-z\x80-\xFF";
return (bool) preg_match("(^
https?://(
(([-_0-9$alpha]+\\.)* # subdomain
[0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)? # domain
[$alpha]([-0-9$alpha]{0,17}[$alpha])? # top domain
|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3} # IPv4
|\[[0-9a-f:]{3,39}\] # IPv6
)(:\\d{1,5})? # port
(/\\S*)? # path
\\z)ix", $value);
}
/**
* Finds whether a string is a valid URI according to RFC 1738.
* @param string
* @return bool
*/
public static function isUri($value)
{
return (bool) preg_match('#^[a-z\d+\.-]+:\S+\z#i', $value);
}
/**
* Checks whether the input is a class, interface or trait.
* @param string
* @return bool
*/
public static function isType($type)
{
return class_exists($type) || interface_exists($type) || trait_exists($type);
}
/**
* Checks whether the input is a valid PHP identifier.
* @return bool
*/
public static function isPhpIdentifier($value)
{
return is_string($value) && preg_match('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\z#', $value);
}
}
Nette-2.4-20160731/Nette/Utils/Strings.php 0000644 0000000 0000000 00000036751 12747434604 016405 0 ustar root root = 0xD800 && $code <= 0xDFFF) || $code > 0x10FFFF) {
throw new Nette\InvalidArgumentException('Code point must be in range 0x0 to 0xD7FF or 0xE000 to 0x10FFFF.');
}
return iconv('UTF-32BE', 'UTF-8//IGNORE', pack('N', $code));
}
/**
* Starts the $haystack string with the prefix $needle?
* @param string
* @param string
* @return bool
*/
public static function startsWith($haystack, $needle)
{
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
/**
* Ends the $haystack string with the suffix $needle?
* @param string
* @param string
* @return bool
*/
public static function endsWith($haystack, $needle)
{
return strlen($needle) === 0 || substr($haystack, -strlen($needle)) === $needle;
}
/**
* Does $haystack contain $needle?
* @param string
* @param string
* @return bool
*/
public static function contains($haystack, $needle)
{
return strpos($haystack, $needle) !== FALSE;
}
/**
* Returns a part of UTF-8 string.
* @param string
* @param int in characters (code points)
* @param int in characters (code points)
* @return string
*/
public static function substring($s, $start, $length = NULL)
{
if (function_exists('mb_substr')) {
return mb_substr($s, $start, $length, 'UTF-8'); // MB is much faster
} elseif ($length === NULL) {
$length = self::length($s);
} elseif ($start < 0 && $length < 0) {
$start += self::length($s); // unifies iconv_substr behavior with mb_substr
}
return iconv_substr($s, $start, $length, 'UTF-8');
}
/**
* Removes special controls characters and normalizes line endings and spaces.
* @param string UTF-8 encoding
* @return string
*/
public static function normalize($s)
{
$s = self::normalizeNewLines($s);
// remove control characters; leave \t + \n
$s = preg_replace('#[\x00-\x08\x0B-\x1F\x7F-\x9F]+#u', '', $s);
// right trim
$s = preg_replace('#[\t ]+$#m', '', $s);
// leading and trailing blank lines
$s = trim($s, "\n");
return $s;
}
/**
* Standardize line endings to unix-like.
* @param string UTF-8 encoding or 8-bit
* @return string
*/
public static function normalizeNewLines($s)
{
return str_replace(["\r\n", "\r"], "\n", $s);
}
/**
* Converts to ASCII.
* @param string UTF-8 encoding
* @return string ASCII
*/
public static function toAscii($s)
{
static $transliterator = NULL;
if ($transliterator === NULL && class_exists('Transliterator', FALSE)) {
$transliterator = \Transliterator::create('Any-Latin; Latin-ASCII');
}
$s = preg_replace('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{2FF}\x{370}-\x{10FFFF}]#u', '', $s);
$s = strtr($s, '`\'"^~?', "\x01\x02\x03\x04\x05\x06");
$s = str_replace(
["\xE2\x80\x9E", "\xE2\x80\x9C", "\xE2\x80\x9D", "\xE2\x80\x9A", "\xE2\x80\x98", "\xE2\x80\x99", "\xC2\xB0"],
["\x03", "\x03", "\x03", "\x02", "\x02", "\x02", "\x04"], $s
);
if ($transliterator !== NULL) {
$s = $transliterator->transliterate($s);
}
if (ICONV_IMPL === 'glibc') {
$s = str_replace(
["\xC2\xBB", "\xC2\xAB", "\xE2\x80\xA6", "\xE2\x84\xA2", "\xC2\xA9", "\xC2\xAE"],
['>>', '<<', '...', 'TM', '(c)', '(R)'], $s
);
$s = iconv('UTF-8', 'WINDOWS-1250//TRANSLIT//IGNORE', $s);
$s = strtr($s, "\xa5\xa3\xbc\x8c\xa7\x8a\xaa\x8d\x8f\x8e\xaf\xb9\xb3\xbe\x9c\x9a\xba\x9d\x9f\x9e"
. "\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3"
. "\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
. "\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
. "\x96\xa0\x8b\x97\x9b\xa6\xad\xb7",
'ALLSSSSTZZZallssstzzzRAAAALCCCEEEEIIDDNNOOOOxRUUUUYTsraaaalccceeeeiiddnnooooruuuuyt- <->|-.');
$s = preg_replace('#[^\x00-\x7F]++#', '', $s);
} else {
$s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s);
}
$s = str_replace(['`', "'", '"', '^', '~', '?'], '', $s);
return strtr($s, "\x01\x02\x03\x04\x05\x06", '`\'"^~?');
}
/**
* Converts to web safe characters [a-z0-9-] text.
* @param string UTF-8 encoding
* @param string allowed characters
* @param bool
* @return string
*/
public static function webalize($s, $charlist = NULL, $lower = TRUE)
{
$s = self::toAscii($s);
if ($lower) {
$s = strtolower($s);
}
$s = preg_replace('#[^a-z0-9' . ($charlist !== NULL ? preg_quote($charlist, '#') : '') . ']+#i', '-', $s);
$s = trim($s, '-');
return $s;
}
/**
* Truncates string to maximal length.
* @param string UTF-8 encoding
* @param int
* @param string UTF-8 encoding
* @return string
*/
public static function truncate($s, $maxLen, $append = "\xE2\x80\xA6")
{
if (self::length($s) > $maxLen) {
$maxLen = $maxLen - self::length($append);
if ($maxLen < 1) {
return $append;
} elseif ($matches = self::match($s, '#^.{1,'.$maxLen.'}(?=[\s\x00-/:-@\[-`{-~])#us')) {
return $matches[0] . $append;
} else {
return self::substring($s, 0, $maxLen) . $append;
}
}
return $s;
}
/**
* Indents the content from the left.
* @param string UTF-8 encoding or 8-bit
* @param int
* @param string
* @return string
*/
public static function indent($s, $level = 1, $chars = "\t")
{
if ($level > 0) {
$s = self::replace($s, '#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level));
}
return $s;
}
/**
* Convert to lower case.
* @param string UTF-8 encoding
* @return string
*/
public static function lower($s)
{
return mb_strtolower($s, 'UTF-8');
}
/**
* Convert first character to lower case.
* @param string UTF-8 encoding
* @return string
*/
public static function firstLower($s)
{
return self::lower(self::substring($s, 0, 1)) . self::substring($s, 1);
}
/**
* Convert to upper case.
* @param string UTF-8 encoding
* @return string
*/
public static function upper($s)
{
return mb_strtoupper($s, 'UTF-8');
}
/**
* Convert first character to upper case.
* @param string UTF-8 encoding
* @return string
*/
public static function firstUpper($s)
{
return self::upper(self::substring($s, 0, 1)) . self::substring($s, 1);
}
/**
* Capitalize string.
* @param string UTF-8 encoding
* @return string
*/
public static function capitalize($s)
{
return mb_convert_case($s, MB_CASE_TITLE, 'UTF-8');
}
/**
* Case-insensitive compares UTF-8 strings.
* @param string
* @param string
* @param int
* @return bool
*/
public static function compare($left, $right, $len = NULL)
{
if ($len < 0) {
$left = self::substring($left, $len, -$len);
$right = self::substring($right, $len, -$len);
} elseif ($len !== NULL) {
$left = self::substring($left, 0, $len);
$right = self::substring($right, 0, $len);
}
return self::lower($left) === self::lower($right);
}
/**
* Finds the length of common prefix of strings.
* @param string|array
* @return string
*/
public static function findPrefix(...$strings)
{
if (is_array($strings[0])) {
$strings = $strings[0];
}
$first = array_shift($strings);
for ($i = 0; $i < strlen($first); $i++) {
foreach ($strings as $s) {
if (!isset($s[$i]) || $first[$i] !== $s[$i]) {
while ($i && $first[$i - 1] >= "\x80" && $first[$i] >= "\x80" && $first[$i] < "\xC0") {
$i--;
}
return substr($first, 0, $i);
}
}
}
return $first;
}
/**
* Returns number of characters (not bytes) in UTF-8 string.
* That is the number of Unicode code points which may differ from the number of graphemes.
* @param string
* @return int
*/
public static function length($s)
{
return function_exists('mb_strlen') ? mb_strlen($s, 'UTF-8') : strlen(utf8_decode($s));
}
/**
* Strips whitespace.
* @param string UTF-8 encoding
* @param string
* @return string
*/
public static function trim($s, $charlist = self::TRIM_CHARACTERS)
{
$charlist = preg_quote($charlist, '#');
return self::replace($s, '#^['.$charlist.']+|['.$charlist.']+\z#u', '');
}
/**
* Pad a string to a certain length with another string.
* @param string UTF-8 encoding
* @param int
* @param string
* @return string
*/
public static function padLeft($s, $length, $pad = ' ')
{
$length = max(0, $length - self::length($s));
$padLen = self::length($pad);
return str_repeat($pad, (int) ($length / $padLen)) . self::substring($pad, 0, $length % $padLen) . $s;
}
/**
* Pad a string to a certain length with another string.
* @param string UTF-8 encoding
* @param int
* @param string
* @return string
*/
public static function padRight($s, $length, $pad = ' ')
{
$length = max(0, $length - self::length($s));
$padLen = self::length($pad);
return $s . str_repeat($pad, (int) ($length / $padLen)) . self::substring($pad, 0, $length % $padLen);
}
/**
* Reverse string.
* @param string UTF-8 encoding
* @return string
*/
public static function reverse($s)
{
return iconv('UTF-32LE', 'UTF-8', strrev(iconv('UTF-8', 'UTF-32BE', $s)));
}
/**
* Use Nette\Utils\Random::generate
* @deprecated
*/
public static function random($length = 10, $charlist = '0-9a-z')
{
trigger_error(__METHOD__ . '() is deprecated, use Nette\Utils\Random::generate()', E_USER_DEPRECATED);
return Random::generate($length, $charlist);
}
/**
* Returns part of $haystack before $nth occurence of $needle.
* @param string
* @param string
* @param int negative value means searching from the end
* @return string|FALSE returns FALSE if the needle was not found
*/
public static function before($haystack, $needle, $nth = 1)
{
$pos = self::pos($haystack, $needle, $nth);
return $pos === FALSE
? FALSE
: substr($haystack, 0, $pos);
}
/**
* Returns part of $haystack after $nth occurence of $needle.
* @param string
* @param string
* @param int negative value means searching from the end
* @return string|FALSE returns FALSE if the needle was not found
*/
public static function after($haystack, $needle, $nth = 1)
{
$pos = self::pos($haystack, $needle, $nth);
return $pos === FALSE
? FALSE
: (string) substr($haystack, $pos + strlen($needle));
}
/**
* Returns position of $nth occurence of $needle in $haystack.
* @param string
* @param string
* @param int negative value means searching from the end
* @return int|FALSE offset in characters or FALSE if the needle was not found
*/
public static function indexOf($haystack, $needle, $nth = 1)
{
$pos = self::pos($haystack, $needle, $nth);
return $pos === FALSE
? FALSE
: self::length(substr($haystack, 0, $pos));
}
/**
* Returns position of $nth occurence of $needle in $haystack.
* @return int|FALSE offset in bytes or FALSE if the needle was not found
*/
private static function pos($haystack, $needle, $nth = 1)
{
if (!$nth) {
return FALSE;
} elseif ($nth > 0) {
if (strlen($needle) === 0) {
return 0;
}
$pos = 0;
while (FALSE !== ($pos = strpos($haystack, $needle, $pos)) && --$nth) {
$pos++;
}
} else {
$len = strlen($haystack);
if (strlen($needle) === 0) {
return $len;
}
$pos = $len - 1;
while (FALSE !== ($pos = strrpos($haystack, $needle, $pos - $len)) && ++$nth) {
$pos--;
}
}
return $pos;
}
/**
* Splits string by a regular expression.
* @param string
* @param string
* @param int
* @return array
*/
public static function split($subject, $pattern, $flags = 0)
{
return self::pcre('preg_split', [$pattern, $subject, -1, $flags | PREG_SPLIT_DELIM_CAPTURE]);
}
/**
* Performs a regular expression match.
* @param string
* @param string
* @param int can be PREG_OFFSET_CAPTURE (returned in bytes)
* @param int offset in bytes
* @return mixed
*/
public static function match($subject, $pattern, $flags = 0, $offset = 0)
{
if ($offset > strlen($subject)) {
return NULL;
}
return self::pcre('preg_match', [$pattern, $subject, & $m, $flags, $offset])
? $m
: NULL;
}
/**
* Performs a global regular expression match.
* @param string
* @param string
* @param int can be PREG_OFFSET_CAPTURE (returned in bytes); PREG_SET_ORDER is default
* @param int offset in bytes
* @return array
*/
public static function matchAll($subject, $pattern, $flags = 0, $offset = 0)
{
if ($offset > strlen($subject)) {
return [];
}
self::pcre('preg_match_all', [
$pattern, $subject, & $m,
($flags & PREG_PATTERN_ORDER) ? $flags : ($flags | PREG_SET_ORDER),
$offset,
]);
return $m;
}
/**
* Perform a regular expression search and replace.
* @param string
* @param string|array
* @param string|callable
* @param int
* @return string
*/
public static function replace($subject, $pattern, $replacement = NULL, $limit = -1)
{
if (is_object($replacement) || is_array($replacement)) {
if ($replacement instanceof Nette\Callback) {
trigger_error('Nette\Callback is deprecated, use PHP callback.', E_USER_DEPRECATED);
$replacement = $replacement->getNative();
}
if (!is_callable($replacement, FALSE, $textual)) {
throw new Nette\InvalidStateException("Callback '$textual' is not callable.");
}
return self::pcre('preg_replace_callback', [$pattern, $replacement, $subject, $limit]);
} elseif ($replacement === NULL && is_array($pattern)) {
$replacement = array_values($pattern);
$pattern = array_keys($pattern);
}
return self::pcre('preg_replace', [$pattern, $replacement, $subject, $limit]);
}
/** @internal */
public static function pcre($func, $args)
{
static $messages = [
PREG_INTERNAL_ERROR => 'Internal error',
PREG_BACKTRACK_LIMIT_ERROR => 'Backtrack limit was exhausted',
PREG_RECURSION_LIMIT_ERROR => 'Recursion limit was exhausted',
PREG_BAD_UTF8_ERROR => 'Malformed UTF-8 data',
PREG_BAD_UTF8_OFFSET_ERROR => 'Offset didn\'t correspond to the begin of a valid UTF-8 code point',
6 => 'Failed due to limited JIT stack space', // PREG_JIT_STACKLIMIT_ERROR
];
$res = Callback::invokeSafe($func, $args, function ($message) use ($args) {
// compile-time error, not detectable by preg_last_error
throw new RegexpException($message . ' in pattern: ' . implode(' or ', (array) $args[0]));
});
if (($code = preg_last_error()) // run-time error, but preg_last_error & return code are liars
&& ($res === NULL || !in_array($func, ['preg_filter', 'preg_replace_callback', 'preg_replace']))
) {
throw new RegexpException((isset($messages[$code]) ? $messages[$code] : 'Unknown error')
. ' (pattern: ' . implode(' or ', (array) $args[0]) . ')', $code);
}
return $res;
}
}
Nette-2.4-20160731/Nette/Utils/StaticClass.php 0000644 0000000 0000000 00000001123 12747434604 017152 0 ustar root root $name) || $this->$name instanceof \Traversable) {
foreach ($this->$name as $handler) {
Callback::invokeArgs($handler, $args);
}
} elseif ($this->$name !== NULL) {
throw new UnexpectedValueException("Property $class::$$name must be array or NULL, " . gettype($this->$name) . ' given.');
}
} elseif ($isProp && $this->$name instanceof \Closure) { // closure in property
trigger_error("Invoking closure in property via \$obj->$name() is deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
return call_user_func_array($this->$name, $args);
} elseif (($methods = & ObjectMixin::getMethods($class)) && isset($methods[$name]) && is_array($methods[$name])) { // magic @methods
trigger_error("Magic methods such as $class::$name() are deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
list($op, $rp, $type) = $methods[$name];
if (count($args) !== ($op === 'get' ? 0 : 1)) {
throw new InvalidArgumentException("$class::$name() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.');
} elseif ($type && $args && !ObjectMixin::checkType($args[0], $type)) {
throw new InvalidArgumentException("Argument passed to $class::$name() must be $type, " . gettype($args[0]) . ' given.');
}
if ($op === 'get') {
return $rp->getValue($this);
} elseif ($op === 'set') {
$rp->setValue($this, $args[0]);
} elseif ($op === 'add') {
$val = $rp->getValue($this);
$val[] = $args[0];
$rp->setValue($this, $val);
}
return $this;
} elseif ($cb = ObjectMixin::getExtensionMethod($class, $name)) { // extension methods
trigger_error("Extension methods such as $class::$name() are deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
return Callback::invoke($cb, $this, ...$args);
} else {
ObjectMixin::strictCall($class, $name);
}
}
/**
* @return void
* @throws MemberAccessException
*/
public static function __callStatic($name, $args)
{
ObjectMixin::strictStaticCall(get_called_class(), $name);
}
/**
* @return mixed property value
* @throws MemberAccessException if the property is not defined.
*/
public function & __get($name)
{
$class = get_class($this);
$uname = ucfirst($name);
if ($prop = ObjectMixin::getMagicProperty($class, $name)) { // property getter
if (!($prop & 0b0001)) {
throw new MemberAccessException("Cannot read a write-only property $class::\$$name.");
}
$m = ($prop & 0b0010 ? 'get' : 'is') . $uname;
if ($prop & 0b0100) { // return by reference
return $this->$m();
} else {
$val = $this->$m();
return $val;
}
} elseif ($name === '') {
throw new MemberAccessException("Cannot read a class '$class' property without name.");
} elseif (($methods = & ObjectMixin::getMethods($class)) && isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // old property getter
trigger_error("Missing annotation @property for $class::\$$name used" . ObjectMixin::getSource(), E_USER_DEPRECATED);
if ($methods[$m] === 0) {
$methods[$m] = (new \ReflectionMethod($class, $m))->returnsReference();
}
if ($methods[$m] === TRUE) {
return $this->$m();
} else {
$val = $this->$m();
return $val;
}
} elseif (isset($methods[$name])) { // public method as closure getter
trigger_error("Accessing methods as properties via \$obj->$name is deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
$val = Callback::closure($this, $name);
return $val;
} elseif (isset($methods['set' . $uname])) { // property getter
throw new MemberAccessException("Cannot read a write-only property $class::\$$name.");
} else {
ObjectMixin::strictGet($class, $name);
}
}
/**
* @return void
* @throws MemberAccessException if the property is not defined or is read-only
*/
public function __set($name, $value)
{
$class = get_class($this);
$uname = ucfirst($name);
if (ObjectMixin::hasProperty($class, $name)) { // unsetted property
$this->$name = $value;
} elseif ($prop = ObjectMixin::getMagicProperty($class, $name)) { // property setter
if (!($prop & 0b1000)) {
throw new MemberAccessException("Cannot write to a read-only property $class::\$$name.");
}
$this->{'set' . $name}($value);
} elseif ($name === '') {
throw new MemberAccessException("Cannot write to a class '$class' property without name.");
} elseif (($methods = & ObjectMixin::getMethods($class)) && isset($methods[$m = 'set' . $uname])) { // old property setter
trigger_error("Missing annotation @property for $class::\$$name used" . ObjectMixin::getSource(), E_USER_DEPRECATED);
$this->$m($value);
} elseif (isset($methods['get' . $uname]) || isset($methods['is' . $uname])) { // property setter
throw new MemberAccessException("Cannot write to a read-only property $class::\$$name.");
} else {
ObjectMixin::strictSet($class, $name);
}
}
/**
* @return void
* @throws MemberAccessException
*/
public function __unset($name)
{
$class = get_class($this);
if (!ObjectMixin::hasProperty($class, $name)) {
throw new MemberAccessException("Cannot unset the property $class::\$$name.");
}
}
/**
* @return bool
*/
public function __isset($name)
{
$uname = ucfirst($name);
return ObjectMixin::getMagicProperty(get_class($this), $name)
|| ($name !== '' && ($methods = ObjectMixin::getMethods(get_class($this))) && (isset($methods['get' . $uname]) || isset($methods['is' . $uname])));
}
/**
* @return Reflection\ClassType|\ReflectionClass
* @deprecated
*/
public static function getReflection()
{
trigger_error(get_called_class() . '::getReflection() is deprecated' . ObjectMixin::getSource(), E_USER_DEPRECATED);
$class = class_exists(Reflection\ClassType::class) ? Reflection\ClassType::class : \ReflectionClass::class;
return new $class(get_called_class());
}
/**
* @return mixed
* @deprecated use Nette\Utils\ObjectMixin::setExtensionMethod()
*/
public static function extensionMethod($name, $callback = NULL)
{
if (strpos($name, '::') === FALSE) {
$class = get_called_class();
} else {
list($class, $name) = explode('::', $name);
$class = (new \ReflectionClass($class))->getName();
}
trigger_error("Extension methods such as $class::$name() are deprecated" . ObjectMixin::getSource(), E_USER_DEPRECATED);
if ($callback === NULL) {
return ObjectMixin::getExtensionMethod($class, $name);
} else {
ObjectMixin::setExtensionMethod($class, $name, $callback);
}
}
}
Nette-2.4-20160731/Nette/Utils/Random.php 0000644 0000000 0000000 00000004016 12747434604 016161 0 ustar root root = 70000) {
for ($i = 0; $i < $length; $i++) {
$res .= $charlist[random_int(0, $chLen - 1)];
}
return $res;
}
$bytes = '';
if (function_exists('openssl_random_pseudo_bytes')) {
$bytes = (string) openssl_random_pseudo_bytes($length, $secure);
if (!$secure) {
$bytes = '';
}
}
if (strlen($bytes) < $length && function_exists('mcrypt_create_iv')) {
$bytes = (string) mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
}
if (strlen($bytes) < $length && !defined('PHP_WINDOWS_VERSION_BUILD') && is_readable('/dev/urandom')) {
$bytes = (string) file_get_contents('/dev/urandom', FALSE, NULL, -1, $length);
}
if (strlen($bytes) < $length) {
$rand3 = md5(serialize($_SERVER), TRUE);
$charlist = str_shuffle($charlist);
for ($i = 0; $i < $length; $i++) {
if ($i % 5 === 0) {
list($rand1, $rand2) = explode(' ', microtime());
$rand1 += lcg_value();
}
$rand1 *= $chLen;
$res .= $charlist[($rand1 + $rand2 + ord($rand3[$i % strlen($rand3)])) % $chLen];
$rand1 -= (int) $rand1;
}
return $res;
}
for ($i = 0; $i < $length; $i++) {
$res .= $charlist[($i + ord($bytes[$i])) % $chLen];
}
return $res;
}
}
Nette-2.4-20160731/Nette/Utils/Paginator.php 0000644 0000000 0000000 00000007672 12747434604 016700 0 ustar root root page = (int) $page;
return $this;
}
/**
* Returns current page number.
* @return int
*/
public function getPage()
{
return $this->base + $this->getPageIndex();
}
/**
* Returns first page number.
* @return int
*/
public function getFirstPage()
{
return $this->base;
}
/**
* Returns last page number.
* @return int|NULL
*/
public function getLastPage()
{
return $this->itemCount === NULL ? NULL : $this->base + max(0, $this->getPageCount() - 1);
}
/**
* Sets first page (base) number.
* @param int
* @return self
*/
public function setBase($base)
{
$this->base = (int) $base;
return $this;
}
/**
* Returns first page (base) number.
* @return int
*/
public function getBase()
{
return $this->base;
}
/**
* Returns zero-based page number.
* @return int
*/
protected function getPageIndex()
{
$index = max(0, $this->page - $this->base);
return $this->itemCount === NULL ? $index : min($index, max(0, $this->getPageCount() - 1));
}
/**
* Is the current page the first one?
* @return bool
*/
public function isFirst()
{
return $this->getPageIndex() === 0;
}
/**
* Is the current page the last one?
* @return bool
*/
public function isLast()
{
return $this->itemCount === NULL ? FALSE : $this->getPageIndex() >= $this->getPageCount() - 1;
}
/**
* Returns the total number of pages.
* @return int|NULL
*/
public function getPageCount()
{
return $this->itemCount === NULL ? NULL : (int) ceil($this->itemCount / $this->itemsPerPage);
}
/**
* Sets the number of items to display on a single page.
* @param int
* @return self
*/
public function setItemsPerPage($itemsPerPage)
{
$this->itemsPerPage = max(1, (int) $itemsPerPage);
return $this;
}
/**
* Returns the number of items to display on a single page.
* @return int
*/
public function getItemsPerPage()
{
return $this->itemsPerPage;
}
/**
* Sets the total number of items.
* @param int (or NULL as infinity)
* @return self
*/
public function setItemCount($itemCount)
{
$this->itemCount = ($itemCount === FALSE || $itemCount === NULL) ? NULL : max(0, (int) $itemCount);
return $this;
}
/**
* Returns the total number of items.
* @return int|NULL
*/
public function getItemCount()
{
return $this->itemCount;
}
/**
* Returns the absolute index of the first item on current page.
* @return int
*/
public function getOffset()
{
return $this->getPageIndex() * $this->itemsPerPage;
}
/**
* Returns the absolute index of the first item on current page in countdown paging.
* @return int|NULL
*/
public function getCountdownOffset()
{
return $this->itemCount === NULL
? NULL
: max(0, $this->itemCount - ($this->getPageIndex() + 1) * $this->itemsPerPage);
}
/**
* Returns the number of items on current page.
* @return int|NULL
*/
public function getLength()
{
return $this->itemCount === NULL
? $this->itemsPerPage
: min($this->itemsPerPage, $this->itemCount - $this->getPageIndex() * $this->itemsPerPage);
}
}
Nette-2.4-20160731/Nette/Utils/ObjectMixin.php 0000644 0000000 0000000 00000036377 12747434604 017173 0 ustar root root [type => callback]] used by extension methods */
private static $extMethods = [];
/********************* strictness ****************d*g**/
/**
* @throws MemberAccessException
*/
public static function strictGet($class, $name)
{
$rc = new \ReflectionClass($class);
$hint = self::getSuggestion(array_merge(
array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }),
self::parseFullDoc($rc, '~^[ \t*]*@property(?:-read)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m')
), $name);
throw new MemberAccessException("Cannot read an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.'));
}
/**
* @throws MemberAccessException
*/
public static function strictSet($class, $name)
{
$rc = new \ReflectionClass($class);
$hint = self::getSuggestion(array_merge(
array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }),
self::parseFullDoc($rc, '~^[ \t*]*@property(?:-write)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m')
), $name);
throw new MemberAccessException("Cannot write to an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.'));
}
/**
* @throws MemberAccessException
*/
public static function strictCall($class, $method, $additionalMethods = [])
{
$hint = self::getSuggestion(array_merge(
get_class_methods($class),
self::parseFullDoc(new \ReflectionClass($class), '~^[ \t*]*@method[ \t]+(?:\S+[ \t]+)??(\w+)\(~m'),
$additionalMethods
), $method);
if (method_exists($class, $method)) { // called parent::$method()
$class = 'parent';
}
throw new MemberAccessException("Call to undefined method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.'));
}
/**
* @throws MemberAccessException
*/
public static function strictStaticCall($class, $method)
{
$hint = self::getSuggestion(
array_filter((new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC), function ($m) { return $m->isStatic(); }),
$method
);
throw new MemberAccessException("Call to undefined static method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.'));
}
/********************* Nette\Object ****************d*g**/
/**
* __call() implementation.
* @param object
* @param string
* @param array
* @return mixed
* @throws MemberAccessException
*/
public static function call($_this, $name, $args)
{
$class = get_class($_this);
$isProp = self::hasProperty($class, $name);
if ($name === '') {
throw new MemberAccessException("Call to class '$class' method without name.");
} elseif ($isProp === 'event') { // calling event handlers
if (is_array($_this->$name) || $_this->$name instanceof \Traversable) {
foreach ($_this->$name as $handler) {
Callback::invokeArgs($handler, $args);
}
} elseif ($_this->$name !== NULL) {
throw new Nette\UnexpectedValueException("Property $class::$$name must be array or NULL, " . gettype($_this->$name) . ' given.');
}
} elseif ($isProp && $_this->$name instanceof \Closure) { // closure in property
return call_user_func_array($_this->$name, $args);
} elseif (($methods = & self::getMethods($class)) && isset($methods[$name]) && is_array($methods[$name])) { // magic @methods
list($op, $rp, $type) = $methods[$name];
if (count($args) !== ($op === 'get' ? 0 : 1)) {
throw new Nette\InvalidArgumentException("$class::$name() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.');
} elseif ($type && $args && !self::checkType($args[0], $type)) {
throw new Nette\InvalidArgumentException("Argument passed to $class::$name() must be $type, " . gettype($args[0]) . ' given.');
}
if ($op === 'get') {
return $rp->getValue($_this);
} elseif ($op === 'set') {
$rp->setValue($_this, $args[0]);
} elseif ($op === 'add') {
$val = $rp->getValue($_this);
$val[] = $args[0];
$rp->setValue($_this, $val);
}
return $_this;
} elseif ($cb = self::getExtensionMethod($class, $name)) { // extension methods
return Callback::invoke($cb, $_this, ...$args);
} else {
self::strictCall($class, $name, array_keys(self::getExtensionMethods($class)));
}
}
/**
* __callStatic() implementation.
* @param string
* @param string
* @param array
* @return void
* @throws MemberAccessException
*/
public static function callStatic($class, $method, $args)
{
self::strictStaticCall($class, $method);
}
/**
* __get() implementation.
* @param object
* @param string property name
* @return mixed property value
* @throws MemberAccessException if the property is not defined.
*/
public static function & get($_this, $name)
{
$class = get_class($_this);
$uname = ucfirst($name);
$methods = & self::getMethods($class);
if ($name === '') {
throw new MemberAccessException("Cannot read a class '$class' property without name.");
} elseif (isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // property getter
if ($methods[$m] === 0) {
$methods[$m] = (new \ReflectionMethod($class, $m))->returnsReference();
}
if ($methods[$m] === TRUE) {
return $_this->$m();
} else {
$val = $_this->$m();
return $val;
}
} elseif (isset($methods[$name])) { // public method as closure getter
if (preg_match('#^(is|get|has)([A-Z]|$)#', $name) && !(new \ReflectionMethod($class, $name))->getNumberOfRequiredParameters()) {
trigger_error("Did you forget parentheses after $name" . self::getSource() . '?', E_USER_WARNING);
}
$val = Callback::closure($_this, $name);
return $val;
} elseif (isset($methods['set' . $uname])) { // property getter
throw new MemberAccessException("Cannot read a write-only property $class::\$$name.");
} else {
self::strictGet($class, $name);
}
}
/**
* __set() implementation.
* @param object
* @param string property name
* @param mixed property value
* @return void
* @throws MemberAccessException if the property is not defined or is read-only
*/
public static function set($_this, $name, $value)
{
$class = get_class($_this);
$uname = ucfirst($name);
$methods = & self::getMethods($class);
if ($name === '') {
throw new MemberAccessException("Cannot write to a class '$class' property without name.");
} elseif (self::hasProperty($class, $name)) { // unsetted property
$_this->$name = $value;
} elseif (isset($methods[$m = 'set' . $uname])) { // property setter
$_this->$m($value);
} elseif (isset($methods['get' . $uname]) || isset($methods['is' . $uname])) { // property setter
throw new MemberAccessException("Cannot write to a read-only property $class::\$$name.");
} else {
self::strictSet($class, $name);
}
}
/**
* __unset() implementation.
* @param object
* @param string property name
* @return void
* @throws MemberAccessException
*/
public static function remove($_this, $name)
{
$class = get_class($_this);
if (!self::hasProperty($class, $name)) {
throw new MemberAccessException("Cannot unset the property $class::\$$name.");
}
}
/**
* __isset() implementation.
* @param object
* @param string property name
* @return bool
*/
public static function has($_this, $name)
{
$name = ucfirst($name);
$methods = & self::getMethods(get_class($_this));
return $name !== '' && (isset($methods['get' . $name]) || isset($methods['is' . $name]));
}
/********************* magic @properties ****************d*g**/
/**
* Returns array of magic properties defined by annotation @property.
* @return array of [name => bit mask]
*/
public static function getMagicProperties($class)
{
static $cache;
$props = & $cache[$class];
if ($props !== NULL) {
return $props;
}
$rc = new \ReflectionClass($class);
preg_match_all(
'~^ [ \t*]* @property(|-read|-write) [ \t]+ [^\s$]+ [ \t]+ \$ (\w+) ()~mx',
(string) $rc->getDocComment(), $matches, PREG_SET_ORDER
);
$props = [];
foreach ($matches as list(, $type, $name)) {
$uname = ucfirst($name);
$write = $type !== '-read'
&& $rc->hasMethod($nm = 'set' . $uname)
&& ($rm = $rc->getMethod($nm)) && $rm->getName() === $nm && !$rm->isPrivate() && !$rm->isStatic();
$read = $type !== '-write'
&& ($rc->hasMethod($nm = 'get' . $uname) || $rc->hasMethod($nm = 'is' . $uname))
&& ($rm = $rc->getMethod($nm)) && $rm->getName() === $nm && !$rm->isPrivate() && !$rm->isStatic();
if ($read || $write) {
$props[$name] = $read << 0 | ($nm[0] === 'g') << 1 | $rm->returnsReference() << 2 | $write << 3;
}
}
if ($parent = get_parent_class($class)) {
$props += self::getMagicProperties($parent);
}
return $props;
}
/** @internal */
public static function getMagicProperty($class, $name)
{
$props = self::getMagicProperties($class);
return isset($props[$name]) ? $props[$name] : NULL;
}
/********************* magic @methods ****************d*g**/
/**
* Returns array of magic methods defined by annotation @method.
* @return array
*/
public static function getMagicMethods($class)
{
$rc = new \ReflectionClass($class);
preg_match_all('~^
[ \t*]* @method [ \t]+
(?: [^\s(]+ [ \t]+ )?
(set|get|is|add) ([A-Z]\w*)
(?: ([ \t]* \() [ \t]* ([^)$\s]*) )?
()~mx', (string) $rc->getDocComment(), $matches, PREG_SET_ORDER);
$methods = [];
foreach ($matches as list(, $op, $prop, $bracket, $type)) {
if ($bracket !== '(') {
trigger_error("Bracket must be immediately after @method $op$prop() in class $class.", E_USER_WARNING);
}
$name = $op . $prop;
$prop = strtolower($prop[0]) . substr($prop, 1) . ($op === 'add' ? 's' : '');
if ($rc->hasProperty($prop) && ($rp = $rc->getProperty($prop)) && !$rp->isStatic()) {
$rp->setAccessible(TRUE);
if ($op === 'get' || $op === 'is') {
$type = NULL;
$op = 'get';
} elseif (!$type && preg_match('#@var[ \t]+(\S+)' . ($op === 'add' ? '\[\]#' : '#'), (string) $rp->getDocComment(), $m)) {
$type = $m[1];
}
if ($rc->inNamespace() && preg_match('#^[A-Z]\w+(\[|\||\z)#', (string) $type)) {
$type = $rc->getNamespaceName() . '\\' . $type;
}
$methods[$name] = [$op, $rp, $type];
}
}
return $methods;
}
/**
* Finds whether a variable is of expected type and do non-data-loss conversion.
* @return bool
* @internal
*/
public static function checkType(& $val, $type)
{
if (strpos($type, '|') !== FALSE) {
$found = NULL;
foreach (explode('|', $type) as $type) {
$tmp = $val;
if (self::checkType($tmp, $type)) {
if ($val === $tmp) {
return TRUE;
}
$found[] = $tmp;
}
}
if ($found) {
$val = $found[0];
return TRUE;
}
return FALSE;
} elseif (substr($type, -2) === '[]') {
if (!is_array($val)) {
return FALSE;
}
$type = substr($type, 0, -2);
$res = [];
foreach ($val as $k => $v) {
if (!self::checkType($v, $type)) {
return FALSE;
}
$res[$k] = $v;
}
$val = $res;
return TRUE;
}
switch (strtolower($type)) {
case NULL:
case 'mixed':
return TRUE;
case 'bool':
case 'boolean':
return ($val === NULL || is_scalar($val)) && settype($val, 'bool');
case 'string':
return ($val === NULL || is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) && settype($val, 'string');
case 'int':
case 'integer':
return ($val === NULL || is_bool($val) || is_numeric($val)) && ((float) (int) $val === (float) $val) && settype($val, 'int');
case 'float':
return ($val === NULL || is_bool($val) || is_numeric($val)) && settype($val, 'float');
case 'scalar':
case 'array':
case 'object':
case 'callable':
case 'resource':
case 'null':
return call_user_func("is_$type", $val);
default:
return $val instanceof $type;
}
}
/********************* extension methods ****************d*g**/
/**
* Adds a method to class.
* @param string
* @param string
* @param mixed callable
* @return void
*/
public static function setExtensionMethod($class, $name, $callback)
{
$name = strtolower($name);
self::$extMethods[$name][$class] = Callback::check($callback);
self::$extMethods[$name][''] = NULL;
}
/**
* Returns extension method.
* @param string
* @param string
* @return mixed
*/
public static function getExtensionMethod($class, $name)
{
$list = & self::$extMethods[strtolower($name)];
$cache = & $list[''][$class];
if (isset($cache)) {
return $cache;
}
foreach ([$class] + class_parents($class) + class_implements($class) as $cl) {
if (isset($list[$cl])) {
return $cache = $list[$cl];
}
}
return $cache = FALSE;
}
/**
* Returns extension methods.
* @param string
* @return array
*/
public static function getExtensionMethods($class)
{
$res = [];
foreach (array_keys(self::$extMethods) as $name) {
if ($cb = self::getExtensionMethod($class, $name)) {
$res[$name] = $cb;
}
}
return $res;
}
/********************* utilities ****************d*g**/
/**
* Finds the best suggestion (for 8-bit encoding).
* @return string|NULL
* @internal
*/
public static function getSuggestion(array $possibilities, $value)
{
$norm = preg_replace($re = '#^(get|set|has|is|add)(?=[A-Z])#', '', $value);
$best = NULL;
$min = (strlen($value) / 4 + 1) * 10 + .1;
foreach (array_unique($possibilities, SORT_REGULAR) as $item) {
$item = $item instanceof \Reflector ? $item->getName() : $item;
if ($item !== $value && (
($len = levenshtein($item, $value, 10, 11, 10)) < $min
|| ($len = levenshtein(preg_replace($re, '', $item), $norm, 10, 11, 10) + 20) < $min
)) {
$min = $len;
$best = $item;
}
}
return $best;
}
private static function parseFullDoc(\ReflectionClass $rc, $pattern)
{
do {
$doc[] = $rc->getDocComment();
} while ($rc = $rc->getParentClass());
return preg_match_all($pattern, implode($doc), $m) ? $m[1] : [];
}
/**
* Checks if the public non-static property exists.
* @return bool|'event'
* @internal
*/
public static function hasProperty($class, $name)
{
static $cache;
$prop = & $cache[$class][$name];
if ($prop === NULL) {
$prop = FALSE;
try {
$rp = new \ReflectionProperty($class, $name);
if ($rp->isPublic() && !$rp->isStatic()) {
$prop = $name >= 'onA' && $name < 'on_' ? 'event' : TRUE;
}
} catch (\ReflectionException $e) {
}
}
return $prop;
}
/**
* Returns array of public (static, non-static and magic) methods.
* @return array
* @internal
*/
public static function & getMethods($class)
{
static $cache;
if (!isset($cache[$class])) {
$cache[$class] = array_fill_keys(get_class_methods($class), 0) + self::getMagicMethods($class);
if ($parent = get_parent_class($class)) {
$cache[$class] += self::getMethods($parent);
}
}
return $cache[$class];
}
/** @internal */
public static function getSource()
{
foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $item) {
if (isset($item['file']) && dirname($item['file']) !== __DIR__) {
return " in $item[file]:$item[line]";
}
}
}
}
Nette-2.4-20160731/Nette/Utils/Object.php 0000644 0000000 0000000 00000010261 12747434604 016146 0 ustar root root
* $val = $obj->label; // equivalent to $val = $obj->getLabel();
* $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette');
*
* Property names are case-sensitive, and they are written in the camelCaps
* or PascalCaps.
*
* Event functionality is provided by declaration of property named 'on{Something}'
* Multiple handlers are allowed.
*
* public $onClick; // declaration in class
* $this->onClick[] = 'callback'; // attaching event handler
* if (!empty($this->onClick)) ... // are there any handlers?
* $this->onClick($sender, $arg); // raises the event with arguments
*
*
* Adding method to class (i.e. to all instances) works similar to JavaScript
* prototype property. The syntax for adding a new method is:
*
* MyClass::extensionMethod('newMethod', function (MyClass $obj, $arg, ...) { ... });
* $obj = new MyClass;
* $obj->newMethod($x);
*
*
* @property-read Nette\Reflection\ClassType|\ReflectionClass $reflection
*/
abstract class Object
{
/**
* Access to reflection.
* @return Nette\Reflection\ClassType|\ReflectionClass
*/
public static function getReflection()
{
$class = class_exists(Nette\Reflection\ClassType::class) ? Nette\Reflection\ClassType::class : 'ReflectionClass';
return new $class(get_called_class());
}
/**
* Call to undefined method.
* @param string method name
* @param array arguments
* @return mixed
* @throws MemberAccessException
*/
public function __call($name, $args)
{
return Nette\Utils\ObjectMixin::call($this, $name, $args);
}
/**
* Call to undefined static method.
* @param string method name (in lower case!)
* @param array arguments
* @return mixed
* @throws MemberAccessException
*/
public static function __callStatic($name, $args)
{
return Nette\Utils\ObjectMixin::callStatic(get_called_class(), $name, $args);
}
/**
* Adding method to class.
* @param string method name
* @param callable
* @return mixed
*/
public static function extensionMethod($name, $callback = NULL)
{
if (strpos($name, '::') === FALSE) {
$class = get_called_class();
} else {
list($class, $name) = explode('::', $name);
$class = (new \ReflectionClass($class))->getName();
}
if ($callback === NULL) {
return Nette\Utils\ObjectMixin::getExtensionMethod($class, $name);
} else {
Nette\Utils\ObjectMixin::setExtensionMethod($class, $name, $callback);
}
}
/**
* Returns property value. Do not call directly.
* @param string property name
* @return mixed property value
* @throws MemberAccessException if the property is not defined.
*/
public function &__get($name)
{
return Nette\Utils\ObjectMixin::get($this, $name);
}
/**
* Sets value of a property. Do not call directly.
* @param string property name
* @param mixed property value
* @return void
* @throws MemberAccessException if the property is not defined or is read-only
*/
public function __set($name, $value)
{
Nette\Utils\ObjectMixin::set($this, $name, $value);
}
/**
* Is property defined?
* @param string property name
* @return bool
*/
public function __isset($name)
{
return Nette\Utils\ObjectMixin::has($this, $name);
}
/**
* Access to undeclared property.
* @param string property name
* @return void
* @throws MemberAccessException
*/
public function __unset($name)
{
Nette\Utils\ObjectMixin::remove($this, $name);
}
}
Nette-2.4-20160731/Nette/Utils/Json.php 0000644 0000000 0000000 00000003771 12747434604 015661 0 ustar root root
* $image = Image::fromFile('nette.jpg');
* $image->resize(150, 100);
* $image->sharpen();
* $image->send();
*
*
* @method void alphaBlending(bool $on)
* @method void antialias(bool $on)
* @method void arc($x, $y, $w, $h, $start, $end, $color)
* @method void char(int $font, $x, $y, string $char, $color)
* @method void charUp(int $font, $x, $y, string $char, $color)
* @method int colorAllocate($red, $green, $blue)
* @method int colorAllocateAlpha($red, $green, $blue, $alpha)
* @method int colorAt($x, $y)
* @method int colorClosest($red, $green, $blue)
* @method int colorClosestAlpha($red, $green, $blue, $alpha)
* @method int colorClosestHWB($red, $green, $blue)
* @method void colorDeallocate($color)
* @method int colorExact($red, $green, $blue)
* @method int colorExactAlpha($red, $green, $blue, $alpha)
* @method void colorMatch(Image $image2)
* @method int colorResolve($red, $green, $blue)
* @method int colorResolveAlpha($red, $green, $blue, $alpha)
* @method void colorSet($index, $red, $green, $blue)
* @method array colorsForIndex($index)
* @method int colorsTotal()
* @method int colorTransparent($color = NULL)
* @method void convolution(array $matrix, float $div, float $offset)
* @method void copy(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH)
* @method void copyMerge(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH, $opacity)
* @method void copyMergeGray(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH, $opacity)
* @method void copyResampled(Image $src, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH)
* @method void copyResized(Image $src, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH)
* @method Image cropAuto(int $mode = -1, float $threshold = .5, int $color = -1)
* @method void dashedLine($x1, $y1, $x2, $y2, $color)
* @method void ellipse($cx, $cy, $w, $h, $color)
* @method void fill($x, $y, $color)
* @method void filledArc($cx, $cy, $w, $h, $s, $e, $color, $style)
* @method void filledEllipse($cx, $cy, $w, $h, $color)
* @method void filledPolygon(array $points, $numPoints, $color)
* @method void filledRectangle($x1, $y1, $x2, $y2, $color)
* @method void fillToBorder($x, $y, $border, $color)
* @method void filter($filtertype)
* @method void flip(int $mode)
* @method array ftText($size, $angle, $x, $y, $col, string $fontFile, string $text, array $extrainfo = NULL)
* @method void gammaCorrect(float $inputgamma, float $outputgamma)
* @method int interlace($interlace = NULL)
* @method bool isTrueColor()
* @method void layerEffect($effect)
* @method void line($x1, $y1, $x2, $y2, $color)
* @method void paletteCopy(Image $source)
* @method void paletteToTrueColor()
* @method void polygon(array $points, $numPoints, $color)
* @method array psText(string $text, $font, $size, $color, $backgroundColor, $x, $y, $space = NULL, $tightness = NULL, float $angle = NULL, $antialiasSteps = NULL)
* @method void rectangle($x1, $y1, $x2, $y2, $col)
* @method Image rotate(float $angle, $backgroundColor)
* @method void saveAlpha(bool $saveflag)
* @method Image scale(int $newWidth, int $newHeight = -1, int $mode = IMG_BILINEAR_FIXED)
* @method void setBrush(Image $brush)
* @method void setPixel($x, $y, $color)
* @method void setStyle(array $style)
* @method void setThickness($thickness)
* @method void setTile(Image $tile)
* @method void string($font, $x, $y, string $s, $col)
* @method void stringUp($font, $x, $y, string $s, $col)
* @method void trueColorToPalette(bool $dither, $ncolors)
* @method array ttfText($size, $angle, $x, $y, $color, string $fontfile, string $text)
* @property-read int $width
* @property-read int $height
* @property-read resource $imageResource
*/
class Image
{
use Nette\SmartObject;
/** {@link resize()} only shrinks images */
const SHRINK_ONLY = 0b0001;
/** {@link resize()} will ignore aspect ratio */
const STRETCH = 0b0010;
/** {@link resize()} fits in given area so its dimensions are less than or equal to the required dimensions */
const FIT = 0b0000;
/** {@link resize()} fills given area so its dimensions are greater than or equal to the required dimensions */
const FILL = 0b0100;
/** {@link resize()} fills given area exactly */
const EXACT = 0b1000;
/** image types */
const JPEG = IMAGETYPE_JPEG,
PNG = IMAGETYPE_PNG,
GIF = IMAGETYPE_GIF;
const EMPTY_GIF = "GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;";
/** @deprecated */
const ENLARGE = 0;
/** @var resource */
private $image;
/**
* Returns RGB color.
* @param int red 0..255
* @param int green 0..255
* @param int blue 0..255
* @param int transparency 0..127
* @return array
*/
public static function rgb($red, $green, $blue, $transparency = 0)
{
return [
'red' => max(0, min(255, (int) $red)),
'green' => max(0, min(255, (int) $green)),
'blue' => max(0, min(255, (int) $blue)),
'alpha' => max(0, min(127, (int) $transparency)),
];
}
/**
* Opens image from file.
* @param string
* @param mixed detected image format
* @throws Nette\NotSupportedException if gd extension is not loaded
* @throws UnknownImageFileException if file not found or file type is not known
* @return self
*/
public static function fromFile($file, & $format = NULL)
{
if (!extension_loaded('gd')) {
throw new Nette\NotSupportedException('PHP extension GD is not loaded.');
}
static $funcs = [
self::JPEG => 'imagecreatefromjpeg',
self::PNG => 'imagecreatefrompng',
self::GIF => 'imagecreatefromgif',
];
$format = @getimagesize($file)[2]; // @ - files smaller than 12 bytes causes read error
if (!isset($funcs[$format])) {
throw new UnknownImageFileException(is_file($file) ? "Unknown type of file '$file'." : "File '$file' not found.");
}
return new static(Callback::invokeSafe($funcs[$format], [$file], function ($message) {
throw new ImageException($message);
}));
}
/**
* Create a new image from the image stream in the string.
* @param string
* @param mixed detected image format
* @return self
* @throws ImageException
*/
public static function fromString($s, & $format = NULL)
{
if (!extension_loaded('gd')) {
throw new Nette\NotSupportedException('PHP extension GD is not loaded.');
}
if (func_num_args() > 1) {
$tmp = @getimagesizefromstring($s)[2]; // @ - strings smaller than 12 bytes causes read error
$format = in_array($tmp, [self::JPEG, self::PNG, self::GIF], TRUE) ? $tmp : NULL;
}
return new static(Callback::invokeSafe('imagecreatefromstring', [$s], function ($message) {
throw new ImageException($message);
}));
}
/**
* Creates blank image.
* @param int
* @param int
* @param array
* @return self
*/
public static function fromBlank($width, $height, $color = NULL)
{
if (!extension_loaded('gd')) {
throw new Nette\NotSupportedException('PHP extension GD is not loaded.');
}
$width = (int) $width;
$height = (int) $height;
if ($width < 1 || $height < 1) {
throw new Nette\InvalidArgumentException('Image width and height must be greater than zero.');
}
$image = imagecreatetruecolor($width, $height);
if (is_array($color)) {
$color += ['alpha' => 0];
$color = imagecolorresolvealpha($image, $color['red'], $color['green'], $color['blue'], $color['alpha']);
imagealphablending($image, FALSE);
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $color);
imagealphablending($image, TRUE);
}
return new static($image);
}
/**
* Wraps GD image.
* @param resource
*/
public function __construct($image)
{
$this->setImageResource($image);
imagesavealpha($image, TRUE);
}
/**
* Returns image width.
* @return int
*/
public function getWidth()
{
return imagesx($this->image);
}
/**
* Returns image height.
* @return int
*/
public function getHeight()
{
return imagesy($this->image);
}
/**
* Sets image resource.
* @param resource
* @return self
*/
protected function setImageResource($image)
{
if (!is_resource($image) || get_resource_type($image) !== 'gd') {
throw new Nette\InvalidArgumentException('Image is not valid.');
}
$this->image = $image;
return $this;
}
/**
* Returns image GD resource.
* @return resource
*/
public function getImageResource()
{
return $this->image;
}
/**
* Resizes image.
* @param mixed width in pixels or percent
* @param mixed height in pixels or percent
* @param int flags
* @return self
*/
public function resize($width, $height, $flags = self::FIT)
{
if ($flags & self::EXACT) {
return $this->resize($width, $height, self::FILL)->crop('50%', '50%', $width, $height);
}
list($newWidth, $newHeight) = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $flags);
if ($newWidth !== $this->getWidth() || $newHeight !== $this->getHeight()) { // resize
$newImage = static::fromBlank($newWidth, $newHeight, self::RGB(0, 0, 0, 127))->getImageResource();
imagecopyresampled(
$newImage, $this->image,
0, 0, 0, 0,
$newWidth, $newHeight, $this->getWidth(), $this->getHeight()
);
$this->image = $newImage;
}
if ($width < 0 || $height < 0) {
imageflip($this->image, $width < 0 ? ($height < 0 ? IMG_FLIP_BOTH : IMG_FLIP_HORIZONTAL) : IMG_FLIP_VERTICAL);
}
return $this;
}
/**
* Calculates dimensions of resized image.
* @param mixed source width
* @param mixed source height
* @param mixed width in pixels or percent
* @param mixed height in pixels or percent
* @param int flags
* @return array
*/
public static function calculateSize($srcWidth, $srcHeight, $newWidth, $newHeight, $flags = self::FIT)
{
if (is_string($newWidth) && substr($newWidth, -1) === '%') {
$newWidth = (int) round($srcWidth / 100 * abs($newWidth));
$percents = TRUE;
} else {
$newWidth = (int) abs($newWidth);
}
if (is_string($newHeight) && substr($newHeight, -1) === '%') {
$newHeight = (int) round($srcHeight / 100 * abs($newHeight));
$flags |= empty($percents) ? 0 : self::STRETCH;
} else {
$newHeight = (int) abs($newHeight);
}
if ($flags & self::STRETCH) { // non-proportional
if (empty($newWidth) || empty($newHeight)) {
throw new Nette\InvalidArgumentException('For stretching must be both width and height specified.');
}
if ($flags & self::SHRINK_ONLY) {
$newWidth = (int) round($srcWidth * min(1, $newWidth / $srcWidth));
$newHeight = (int) round($srcHeight * min(1, $newHeight / $srcHeight));
}
} else { // proportional
if (empty($newWidth) && empty($newHeight)) {
throw new Nette\InvalidArgumentException('At least width or height must be specified.');
}
$scale = [];
if ($newWidth > 0) { // fit width
$scale[] = $newWidth / $srcWidth;
}
if ($newHeight > 0) { // fit height
$scale[] = $newHeight / $srcHeight;
}
if ($flags & self::FILL) {
$scale = [max($scale)];
}
if ($flags & self::SHRINK_ONLY) {
$scale[] = 1;
}
$scale = min($scale);
$newWidth = (int) round($srcWidth * $scale);
$newHeight = (int) round($srcHeight * $scale);
}
return [max($newWidth, 1), max($newHeight, 1)];
}
/**
* Crops image.
* @param mixed x-offset in pixels or percent
* @param mixed y-offset in pixels or percent
* @param mixed width in pixels or percent
* @param mixed height in pixels or percent
* @return self
*/
public function crop($left, $top, $width, $height)
{
list($r['x'], $r['y'], $r['width'], $r['height'])
= static::calculateCutout($this->getWidth(), $this->getHeight(), $left, $top, $width, $height);
if (PHP_VERSION_ID > 50611) { // PHP bug #67447
$this->image = imagecrop($this->image, $r);
} else {
$newImage = static::fromBlank($r['width'], $r['height'], self::RGB(0, 0, 0, 127))->getImageResource();
imagecopy($newImage, $this->image, 0, 0, $r['x'], $r['y'], $r['width'], $r['height']);
$this->image = $newImage;
}
return $this;
}
/**
* Calculates dimensions of cutout in image.
* @param mixed source width
* @param mixed source height
* @param mixed x-offset in pixels or percent
* @param mixed y-offset in pixels or percent
* @param mixed width in pixels or percent
* @param mixed height in pixels or percent
* @return array
*/
public static function calculateCutout($srcWidth, $srcHeight, $left, $top, $newWidth, $newHeight)
{
if (is_string($newWidth) && substr($newWidth, -1) === '%') {
$newWidth = (int) round($srcWidth / 100 * $newWidth);
}
if (is_string($newHeight) && substr($newHeight, -1) === '%') {
$newHeight = (int) round($srcHeight / 100 * $newHeight);
}
if (is_string($left) && substr($left, -1) === '%') {
$left = (int) round(($srcWidth - $newWidth) / 100 * $left);
}
if (is_string($top) && substr($top, -1) === '%') {
$top = (int) round(($srcHeight - $newHeight) / 100 * $top);
}
if ($left < 0) {
$newWidth += $left;
$left = 0;
}
if ($top < 0) {
$newHeight += $top;
$top = 0;
}
$newWidth = min($newWidth, $srcWidth - $left);
$newHeight = min($newHeight, $srcHeight - $top);
return [$left, $top, $newWidth, $newHeight];
}
/**
* Sharpen image.
* @return self
*/
public function sharpen()
{
imageconvolution($this->image, [ // my magic numbers ;)
[-1, -1, -1],
[-1, 24, -1],
[-1, -1, -1],
], 16, 0);
return $this;
}
/**
* Puts another image into this image.
* @param Image
* @param mixed x-coordinate in pixels or percent
* @param mixed y-coordinate in pixels or percent
* @param int opacity 0..100
* @return self
*/
public function place(Image $image, $left = 0, $top = 0, $opacity = 100)
{
$opacity = max(0, min(100, (int) $opacity));
if ($opacity === 0) {
return $this;
}
$width = $image->getWidth();
$height = $image->getHeight();
if (is_string($left) && substr($left, -1) === '%') {
$left = (int) round(($this->getWidth() - $width) / 100 * $left);
}
if (is_string($top) && substr($top, -1) === '%') {
$top = (int) round(($this->getHeight() - $height) / 100 * $top);
}
$output = $input = $image->image;
if ($opacity < 100) {
for ($i = 0; $i < 128; $i++) {
$tbl[$i] = round(127 - (127 - $i) * $opacity / 100);
}
$output = imagecreatetruecolor($width, $height);
imagealphablending($output, FALSE);
if (!$image->isTrueColor()) {
$input = $output;
imagefilledrectangle($output, 0, 0, $width, $height, imagecolorallocatealpha($output, 0, 0, 0, 127));
imagecopy($output, $image->image, 0, 0, 0, 0, $width, $height);
}
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {
$c = \imagecolorat($input, $x, $y);
$c = ($c & 0xFFFFFF) + ($tbl[$c >> 24] << 24);
\imagesetpixel($output, $x, $y, $c);
}
}
imagealphablending($output, TRUE);
}
imagecopy(
$this->image, $output,
$left, $top, 0, 0, $width, $height
);
return $this;
}
/**
* Saves image to the file.
* @param string filename
* @param int quality 0..100 (for JPEG and PNG)
* @param int optional image type
* @return bool TRUE on success or FALSE on failure.
*/
public function save($file = NULL, $quality = NULL, $type = NULL)
{
if ($type === NULL) {
switch (strtolower($ext = pathinfo($file, PATHINFO_EXTENSION))) {
case 'jpg':
case 'jpeg':
$type = self::JPEG;
break;
case 'png':
$type = self::PNG;
break;
case 'gif':
$type = self::GIF;
break;
default:
throw new Nette\InvalidArgumentException("Unsupported file extension '$ext'.");
}
}
switch ($type) {
case self::JPEG:
$quality = $quality === NULL ? 85 : max(0, min(100, (int) $quality));
return imagejpeg($this->image, $file, $quality);
case self::PNG:
$quality = $quality === NULL ? 9 : max(0, min(9, (int) $quality));
return imagepng($this->image, $file, $quality);
case self::GIF:
return imagegif($this->image, $file);
default:
throw new Nette\InvalidArgumentException("Unsupported image type '$type'.");
}
}
/**
* Outputs image to string.
* @param int image type
* @param int quality 0..100 (for JPEG and PNG)
* @return string
*/
public function toString($type = self::JPEG, $quality = NULL)
{
ob_start(function () {});
$this->save(NULL, $quality, $type);
return ob_get_clean();
}
/**
* Outputs image to string.
* @return string
*/
public function __toString()
{
try {
return $this->toString();
} catch (\Throwable $e) {
} catch (\Exception $e) {
}
if (isset($e)) {
if (func_num_args()) {
throw $e;
}
trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
}
}
/**
* Outputs image to browser.
* @param int image type
* @param int quality 0..100 (for JPEG and PNG)
* @return bool TRUE on success or FALSE on failure.
*/
public function send($type = self::JPEG, $quality = NULL)
{
if (!in_array($type, [self::JPEG, self::PNG, self::GIF], TRUE)) {
throw new Nette\InvalidArgumentException("Unsupported image type '$type'.");
}
header('Content-Type: ' . image_type_to_mime_type($type));
return $this->save(NULL, $quality, $type);
}
/**
* Call to undefined method.
*
* @param string method name
* @param array arguments
* @return mixed
* @throws Nette\MemberAccessException
*/
public function __call($name, $args)
{
$function = 'image' . $name;
if (!function_exists($function)) {
ObjectMixin::strictCall(get_class($this), $name);
}
foreach ($args as $key => $value) {
if ($value instanceof self) {
$args[$key] = $value->getImageResource();
} elseif (is_array($value) && isset($value['red'])) { // rgb
$args[$key] = imagecolorallocatealpha(
$this->image,
$value['red'], $value['green'], $value['blue'], $value['alpha']
) ?: imagecolorresolvealpha(
$this->image,
$value['red'], $value['green'], $value['blue'], $value['alpha']
);
}
}
$res = $function($this->image, ...$args);
return is_resource($res) && get_resource_type($res) === 'gd' ? $this->setImageResource($res) : $res;
}
public function __clone()
{
ob_start(function () {});
imagegd2($this->image);
$this->setImageResource(imagecreatefromstring(ob_get_clean()));
}
}
Nette-2.4-20160731/Nette/Utils/IHtmlString.php 0000644 0000000 0000000 00000000404 12747434604 017142 0 ustar root root
* $el = Html::el('a')->href($link)->setText('Nette');
* $el->class = 'myclass';
* echo $el;
*
* echo $el->startTag(), $el->endTag();
*
*/
class Html implements \ArrayAccess, \Countable, \IteratorAggregate, IHtmlString
{
use Nette\SmartObject;
/** @var string element's name */
private $name;
/** @var bool is element empty? */
private $isEmpty;
/** @var array element's attributes */
public $attrs = [];
/** @var array of Html | string nodes */
protected $children = [];
/** @var bool use XHTML syntax? */
public static $xhtml = FALSE;
/** @var array empty (void) elements */
public static $emptyElements = [
'img' => 1, 'hr' => 1, 'br' => 1, 'input' => 1, 'meta' => 1, 'area' => 1, 'embed' => 1, 'keygen' => 1,
'source' => 1, 'base' => 1, 'col' => 1, 'link' => 1, 'param' => 1, 'basefont' => 1, 'frame' => 1,
'isindex' => 1, 'wbr' => 1, 'command' => 1, 'track' => 1,
];
/**
* Static factory.
* @param string element name (or NULL)
* @param array|string element's attributes or plain text content
* @return self
*/
public static function el($name = NULL, $attrs = NULL)
{
$el = new static;
$parts = explode(' ', (string) $name, 2);
$el->setName($parts[0]);
if (is_array($attrs)) {
$el->attrs = $attrs;
} elseif ($attrs !== NULL) {
$el->setText($attrs);
}
if (isset($parts[1])) {
foreach (Strings::matchAll($parts[1] . ' ', '#([a-z0-9:-]+)(?:=(["\'])?(.*?)(?(2)\\2|\s))?#i') as $m) {
$el->attrs[$m[1]] = isset($m[3]) ? $m[3] : TRUE;
}
}
return $el;
}
/**
* Changes element's name.
* @param string
* @param bool Is element empty?
* @return self
* @throws Nette\InvalidArgumentException
*/
public function setName($name, $isEmpty = NULL)
{
if ($name !== NULL && !is_string($name)) {
throw new Nette\InvalidArgumentException(sprintf('Name must be string or NULL, %s given.', gettype($name)));
}
$this->name = $name;
$this->isEmpty = $isEmpty === NULL ? isset(static::$emptyElements[$name]) : (bool) $isEmpty;
return $this;
}
/**
* Returns element's name.
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Is element empty?
* @return bool
*/
public function isEmpty()
{
return $this->isEmpty;
}
/**
* Sets multiple attributes.
* @param array
* @return self
*/
public function addAttributes(array $attrs)
{
$this->attrs = array_merge($this->attrs, $attrs);
return $this;
}
/**
* Appends value to element's attribute.
* @param string
* @param string|array value to append
* @param string|bool value option
* @return self
*/
public function appendAttribute($name, $value, $option = TRUE)
{
if (is_array($value)) {
$prev = isset($this->attrs[$name]) ? (array) $this->attrs[$name] : [];
$this->attrs[$name] = $value + $prev;
} elseif ((string) $value === '') {
$tmp = & $this->attrs[$name]; // appending empty value? -> ignore, but ensure it exists
} elseif (!isset($this->attrs[$name]) || is_array($this->attrs[$name])) { // needs array
$this->attrs[$name][$value] = $option;
} else {
$this->attrs[$name] = [$this->attrs[$name] => TRUE, $value => $option];
}
return $this;
}
/**
* Sets element's attribute.
* @param string
* @param mixed
* @return self
*/
public function setAttribute($name, $value)
{
$this->attrs[$name] = $value;
return $this;
}
/**
* Returns element's attribute.
* @param string
* @return mixed
*/
public function getAttribute($name)
{
return isset($this->attrs[$name]) ? $this->attrs[$name] : NULL;
}
/**
* Unsets element's attribute.
* @param string
* @return self
*/
public function removeAttribute($name)
{
unset($this->attrs[$name]);
return $this;
}
/**
* Overloaded setter for element's attribute.
* @param string HTML attribute name
* @param mixed HTML attribute value
* @return void
*/
public function __set($name, $value)
{
$this->attrs[$name] = $value;
}
/**
* Overloaded getter for element's attribute.
* @param string HTML attribute name
* @return mixed HTML attribute value
*/
public function &__get($name)
{
return $this->attrs[$name];
}
/**
* Overloaded tester for element's attribute.
* @param string HTML attribute name
* @return bool
*/
public function __isset($name)
{
return isset($this->attrs[$name]);
}
/**
* Overloaded unsetter for element's attribute.
* @param string HTML attribute name
* @return void
*/
public function __unset($name)
{
unset($this->attrs[$name]);
}
/**
* Overloaded setter for element's attribute.
* @param string HTML attribute name
* @param array (string) HTML attribute value or pair?
* @return mixed
*/
public function __call($m, $args)
{
$p = substr($m, 0, 3);
if ($p === 'get' || $p === 'set' || $p === 'add') {
$m = substr($m, 3);
$m[0] = $m[0] | "\x20";
if ($p === 'get') {
return isset($this->attrs[$m]) ? $this->attrs[$m] : NULL;
} elseif ($p === 'add') {
$args[] = TRUE;
}
}
if (count($args) === 0) { // invalid
} elseif (count($args) === 1) { // set
$this->attrs[$m] = $args[0];
} else { // add
$this->appendAttribute($m, $args[0], $args[1]);
}
return $this;
}
/**
* Special setter for element's attribute.
* @param string path
* @param array query
* @return self
*/
public function href($path, $query = NULL)
{
if ($query) {
$query = http_build_query($query, '', '&');
if ($query !== '') {
$path .= '?' . $query;
}
}
$this->attrs['href'] = $path;
return $this;
}
/**
* Setter for data-* attributes. Booleans are converted to 'true' resp. 'false'.
* @return self
*/
public function data($name, $value = NULL)
{
if (func_num_args() === 1) {
$this->attrs['data'] = $name;
} else {
$this->attrs["data-$name"] = is_bool($value) ? json_encode($value) : $value;
}
return $this;
}
/**
* Sets element's HTML content.
* @param string raw HTML string
* @return self
* @throws Nette\InvalidArgumentException
*/
public function setHtml($html)
{
if (is_array($html)) {
throw new Nette\InvalidArgumentException(sprintf('Textual content must be a scalar, %s given.', gettype($html)));
}
$this->removeChildren();
$this->children[] = (string) $html;
return $this;
}
/**
* Returns element's HTML content.
* @return string
*/
public function getHtml()
{
$s = '';
foreach ($this->children as $child) {
if (is_object($child)) {
$s .= $child->render();
} else {
$s .= $child;
}
}
return $s;
}
/**
* Sets element's textual content.
* @param string
* @return self
* @throws Nette\InvalidArgumentException
*/
public function setText($text)
{
if (!is_array($text) && !$text instanceof self) {
$text = htmlspecialchars((string) $text, ENT_NOQUOTES, 'UTF-8');
}
return $this->setHtml($text);
}
/**
* Returns element's textual content.
* @return string
*/
public function getText()
{
return html_entity_decode(strip_tags($this->getHtml()), ENT_QUOTES, 'UTF-8');
}
/**
* @deprecated
*/
public function add($child)
{
trigger_error(__METHOD__ . '() is deprecated, use addHtml() or addText() instead.', E_USER_DEPRECATED);
return $this->addHtml($child);
}
/**
* Adds new element's child.
* @param Html|string Html node or raw HTML string
* @return self
*/
public function addHtml($child)
{
return $this->insert(NULL, $child);
}
/**
* Appends plain-text string to element content.
* @param string plain-text string
* @return self
*/
public function addText($text)
{
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
return $this->insert(NULL, $text);
}
/**
* Creates and adds a new Html child.
* @param string elements's name
* @param array|string element's attributes or raw HTML string
* @return self created element
*/
public function create($name, $attrs = NULL)
{
$this->insert(NULL, $child = static::el($name, $attrs));
return $child;
}
/**
* Inserts child node.
* @param int|NULL position or NULL for appending
* @param Html|string Html node or raw HTML string
* @param bool
* @return self
* @throws Nette\InvalidArgumentException
*/
public function insert($index, $child, $replace = FALSE)
{
if ($child instanceof self || is_scalar($child)) {
if ($index === NULL) { // append
$this->children[] = $child;
} else { // insert or replace
array_splice($this->children, (int) $index, $replace ? 1 : 0, [$child]);
}
} else {
throw new Nette\InvalidArgumentException(sprintf('Child node must be scalar or Html object, %s given.', is_object($child) ? get_class($child) : gettype($child)));
}
return $this;
}
/**
* Inserts (replaces) child node (\ArrayAccess implementation).
* @param int|NULL position or NULL for appending
* @param Html|string Html node or raw HTML string
* @return void
*/
public function offsetSet($index, $child)
{
$this->insert($index, $child, TRUE);
}
/**
* Returns child node (\ArrayAccess implementation).
* @param int
* @return self|string
*/
public function offsetGet($index)
{
return $this->children[$index];
}
/**
* Exists child node? (\ArrayAccess implementation).
* @param int
* @return bool
*/
public function offsetExists($index)
{
return isset($this->children[$index]);
}
/**
* Removes child node (\ArrayAccess implementation).
* @param int
* @return void
*/
public function offsetUnset($index)
{
if (isset($this->children[$index])) {
array_splice($this->children, (int) $index, 1);
}
}
/**
* Returns children count.
* @return int
*/
public function count()
{
return count($this->children);
}
/**
* Removes all children.
* @return void
*/
public function removeChildren()
{
$this->children = [];
}
/**
* Iterates over elements.
* @return \ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->children);
}
/**
* Returns all children.
* @return array
*/
public function getChildren()
{
return $this->children;
}
/**
* Renders element's start tag, content and end tag.
* @param int
* @return string
*/
public function render($indent = NULL)
{
$s = $this->startTag();
if (!$this->isEmpty) {
// add content
if ($indent !== NULL) {
$indent++;
}
foreach ($this->children as $child) {
if (is_object($child)) {
$s .= $child->render($indent);
} else {
$s .= $child;
}
}
// add end tag
$s .= $this->endTag();
}
if ($indent !== NULL) {
return "\n" . str_repeat("\t", $indent - 1) . $s . "\n" . str_repeat("\t", max(0, $indent - 2));
}
return $s;
}
public function __toString()
{
try {
return $this->render();
} catch (\Throwable $e) {
} catch (\Exception $e) {
}
trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
}
/**
* Returns element's start tag.
* @return string
*/
public function startTag()
{
if ($this->name) {
return '<' . $this->name . $this->attributes() . (static::$xhtml && $this->isEmpty ? ' />' : '>');
} else {
return '';
}
}
/**
* Returns element's end tag.
* @return string
*/
public function endTag()
{
return $this->name && !$this->isEmpty ? '' . $this->name . '>' : '';
}
/**
* Returns element's attributes.
* @return string
* @internal
*/
public function attributes()
{
if (!is_array($this->attrs)) {
return '';
}
$s = '';
$attrs = $this->attrs;
if (isset($attrs['data']) && is_array($attrs['data'])) { // deprecated
trigger_error('Expanded attribute "data" is deprecated.', E_USER_DEPRECATED);
foreach ($attrs['data'] as $key => $value) {
$attrs['data-' . $key] = $value;
}
unset($attrs['data']);
}
foreach ($attrs as $key => $value) {
if ($value === NULL || $value === FALSE) {
continue;
} elseif ($value === TRUE) {
if (static::$xhtml) {
$s .= ' ' . $key . '="' . $key . '"';
} else {
$s .= ' ' . $key;
}
continue;
} elseif (is_array($value)) {
if (strncmp($key, 'data-', 5) === 0) {
$value = Json::encode($value);
} else {
$tmp = NULL;
foreach ($value as $k => $v) {
if ($v != NULL) { // intentionally ==, skip NULLs & empty string
// composite 'style' vs. 'others'
$tmp[] = $v === TRUE ? $k : (is_string($k) ? $k . ':' . $v : $v);
}
}
if ($tmp === NULL) {
continue;
}
$value = implode($key === 'style' || !strncmp($key, 'on', 2) ? ';' : ' ', $tmp);
}
} elseif (is_float($value)) {
$value = rtrim(rtrim(number_format($value, 10, '.', ''), '0'), '.');
} else {
$value = (string) $value;
}
$q = strpos($value, '"') === FALSE ? '"' : "'";
$s .= ' ' . $key . '=' . $q
. str_replace(
['&', $q, '<'],
['&', $q === '"' ? '"' : ''', self::$xhtml ? '<' : '<'],
$value
)
. (strpos($value, '`') !== FALSE && strpbrk($value, ' <>"\'') === FALSE ? ' ' : '')
. $q;
}
$s = str_replace('@', '@', $s);
return $s;
}
/**
* Clones all children too.
*/
public function __clone()
{
foreach ($this->children as $key => $value) {
if (is_object($value)) {
$this->children[$key] = clone $value;
}
}
}
}
Nette-2.4-20160731/Nette/Utils/FileSystem.php 0000644 0000000 0000000 00000010115 12747434604 017022 0 ustar root root getPathname());
}
foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
if ($item->isDir()) {
static::createDir($dest . '/' . $iterator->getSubPathName());
} else {
static::copy($item->getPathname(), $dest . '/' . $iterator->getSubPathName());
}
}
} else {
static::createDir(dirname($dest));
if (@stream_copy_to_stream(fopen($source, 'r'), fopen($dest, 'w')) === FALSE) { // @ is escalated to exception
throw new Nette\IOException("Unable to copy file '$source' to '$dest'.");
}
}
}
/**
* Deletes a file or directory.
* @return void
* @throws Nette\IOException
*/
public static function delete($path)
{
if (is_file($path) || is_link($path)) {
$func = DIRECTORY_SEPARATOR === '\\' && is_dir($path) ? 'rmdir' : 'unlink';
if (!@$func($path)) { // @ is escalated to exception
throw new Nette\IOException("Unable to delete '$path'.");
}
} elseif (is_dir($path)) {
foreach (new \FilesystemIterator($path) as $item) {
static::delete($item->getPathname());
}
if (!@rmdir($path)) { // @ is escalated to exception
throw new Nette\IOException("Unable to delete directory '$path'.");
}
}
}
/**
* Renames a file or directory.
* @return void
* @throws Nette\IOException
* @throws Nette\InvalidStateException if the target file or directory already exist
*/
public static function rename($name, $newName, $overwrite = TRUE)
{
if (!$overwrite && file_exists($newName)) {
throw new Nette\InvalidStateException("File or directory '$newName' already exists.");
} elseif (!file_exists($name)) {
throw new Nette\IOException("File or directory '$name' not found.");
} else {
static::createDir(dirname($newName));
static::delete($newName);
if (!@rename($name, $newName)) { // @ is escalated to exception
throw new Nette\IOException("Unable to rename file or directory '$name' to '$newName'.");
}
}
}
/**
* Reads file content.
* @return string
* @throws Nette\IOException
*/
public static function read($file)
{
$content = @file_get_contents($file); // @ is escalated to exception
if ($content === FALSE) {
throw new Nette\IOException("Unable to read file '$file'.");
}
return $content;
}
/**
* Writes a string to a file.
* @return void
* @throws Nette\IOException
*/
public static function write($file, $content, $mode = 0666)
{
static::createDir(dirname($file));
if (@file_put_contents($file, $content) === FALSE) { // @ is escalated to exception
throw new Nette\IOException("Unable to write file '$file'.");
}
if ($mode !== NULL && !@chmod($file, $mode)) { // @ is escalated to exception
throw new Nette\IOException("Unable to chmod file '$file'.");
}
}
/**
* Is path absolute?
* @return bool
*/
public static function isAbsolute($path)
{
return (bool) preg_match('#([a-z]:)?[/\\\\]|[a-z][a-z0-9+.-]*://#Ai', $path);
}
}
Nette-2.4-20160731/Nette/Utils/exceptions.php 0000644 0000000 0000000 00000005636 12747434604 017133 0 ustar root root format('Y-m-d H:i:s'), $time->getTimezone());
} elseif (is_numeric($time)) {
if ($time <= self::YEAR) {
$time += time();
}
return (new static('@' . $time))->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
} else { // textual or NULL
return new static($time);
}
}
/**
* @return string
*/
public function __toString()
{
return $this->format('Y-m-d H:i:s');
}
/**
* @param string
* @return self
*/
public function modifyClone($modify = '')
{
$dolly = clone $this;
return $modify ? $dolly->modify($modify) : $dolly;
}
/**
* @param int
* @return self
*/
public function setTimestamp($timestamp)
{
$zone = $this->getTimezone();
$this->__construct('@' . $timestamp);
return $this->setTimeZone($zone);
}
/**
* @return int|string
*/
public function getTimestamp()
{
$ts = $this->format('U');
return is_float($tmp = $ts * 1) ? $ts : $tmp;
}
/**
* Returns new DateTime object formatted according to the specified format.
* @param string The format the $time parameter should be in
* @param string String representing the time
* @param string|\DateTimeZone desired timezone (default timezone is used if NULL is passed)
* @return self|FALSE
*/
public static function createFromFormat($format, $time, $timezone = NULL)
{
if ($timezone === NULL) {
$timezone = new \DateTimeZone(date_default_timezone_get());
} elseif (is_string($timezone)) {
$timezone = new \DateTimeZone($timezone);
} elseif (!$timezone instanceof \DateTimeZone) {
throw new Nette\InvalidArgumentException('Invalid timezone given');
}
$date = parent::createFromFormat($format, $time, $timezone);
return $date ? static::from($date) : FALSE;
}
/**
* Returns JSON representation in ISO 8601 (used by JavaScript).
* @return string
*/
public function jsonSerialize()
{
return $this->format('c');
}
}
Nette-2.4-20160731/Nette/Utils/Callback.php 0000644 0000000 0000000 00000011371 12747434604 016437 0 ustar root root getClosure();
} elseif (is_array($callable) && method_exists($callable[0], $callable[1])) {
return (new \ReflectionMethod($callable[0], $callable[1]))->getClosure($callable[0]);
}
self::check($callable);
$_callable_ = $callable;
return function (...$args) use ($_callable_) {
return $_callable_(...$args);
};
}
/**
* Invokes callback.
* @return mixed
*/
public static function invoke($callable, ...$args)
{
self::check($callable);
return call_user_func_array($callable, $args);
}
/**
* Invokes callback with an array of parameters.
* @return mixed
*/
public static function invokeArgs($callable, array $args = [])
{
self::check($callable);
return call_user_func_array($callable, $args);
}
/**
* Invokes internal PHP function with own error handler.
* @param string
* @return mixed
*/
public static function invokeSafe($function, array $args, $onError)
{
$prev = set_error_handler(function ($severity, $message, $file) use ($onError, & $prev, $function) {
if ($file === '' && defined('HHVM_VERSION')) { // https://github.com/facebook/hhvm/issues/4625
$file = func_get_arg(5)[1]['file'];
}
if ($file === __FILE__) {
$msg = preg_replace("#^$function\(.*?\): #", '', $message);
if ($onError($msg, $severity) !== FALSE) {
return;
}
}
return $prev ? $prev(...func_get_args()) : FALSE;
});
try {
$res = $function(...$args);
restore_error_handler();
return $res;
} catch (\Throwable $e) {
restore_error_handler();
throw $e;
} catch (\Exception $e) {
restore_error_handler();
throw $e;
}
}
/**
* @return callable
*/
public static function check($callable, $syntax = FALSE)
{
if (!is_callable($callable, $syntax)) {
throw new Nette\InvalidArgumentException($syntax
? 'Given value is not a callable type.'
: sprintf("Callback '%s' is not callable.", self::toString($callable))
);
}
return $callable;
}
/**
* @return string
*/
public static function toString($callable)
{
if ($callable instanceof \Closure) {
$inner = self::unwrap($callable);
return '{closure' . ($inner instanceof \Closure ? '}' : ' ' . self::toString($inner) . '}');
} elseif (is_string($callable) && $callable[0] === "\0") {
return '{lambda}';
} else {
is_callable($callable, TRUE, $textual);
return $textual;
}
}
/**
* @return \ReflectionMethod|\ReflectionFunction
*/
public static function toReflection($callable)
{
if ($callable instanceof \Closure) {
$callable = self::unwrap($callable);
} elseif ($callable instanceof Nette\Callback) {
trigger_error('Nette\Callback is deprecated.', E_USER_DEPRECATED);
$callable = $callable->getNative();
}
$class = class_exists(Nette\Reflection\Method::class) ? Nette\Reflection\Method::class : 'ReflectionMethod';
if (is_string($callable) && strpos($callable, '::')) {
return new $class($callable);
} elseif (is_array($callable)) {
return new $class($callable[0], $callable[1]);
} elseif (is_object($callable) && !$callable instanceof \Closure) {
return new $class($callable, '__invoke');
} else {
$class = class_exists(Nette\Reflection\GlobalFunction::class) ? Nette\Reflection\GlobalFunction::class : 'ReflectionFunction';
return new $class($callable);
}
}
/**
* @return bool
*/
public static function isStatic($callable)
{
return is_array($callable) ? is_string($callable[0]) : is_string($callable);
}
/**
* Unwraps closure created by self::closure()
* @internal
* @return callable
*/
public static function unwrap(\Closure $closure)
{
$r = new \ReflectionFunction($closure);
if (substr($r->getName(), -1) === '}') {
$vars = $r->getStaticVariables();
return isset($vars['_callable_']) ? $vars['_callable_'] : $closure;
} elseif ($obj = $r->getClosureThis()) {
return [$obj, $r->getName()];
} elseif ($class = $r->getClosureScopeClass()) {
return [$class->getName(), $r->getName()];
} else {
return $r->getName();
}
}
}
Nette-2.4-20160731/Nette/Utils/Arrays.php 0000644 0000000 0000000 00000013254 12747434604 016206 0 ustar root root $v) {
if (is_array($v) && is_array($arr2[$k])) {
$res[$k] = self::mergeTree($v, $arr2[$k]);
}
}
return $res;
}
/**
* Searches the array for a given key and returns the offset if successful.
* @return int|FALSE offset if it is found, FALSE otherwise
*/
public static function searchKey(array $arr, $key)
{
$foo = [$key => NULL];
return array_search(key($foo), array_keys($arr), TRUE);
}
/**
* Inserts new array before item specified by key.
* @return void
*/
public static function insertBefore(array & $arr, $key, array $inserted)
{
$offset = (int) self::searchKey($arr, $key);
$arr = array_slice($arr, 0, $offset, TRUE) + $inserted + array_slice($arr, $offset, count($arr), TRUE);
}
/**
* Inserts new array after item specified by key.
* @return void
*/
public static function insertAfter(array & $arr, $key, array $inserted)
{
$offset = self::searchKey($arr, $key);
$offset = $offset === FALSE ? count($arr) : $offset + 1;
$arr = array_slice($arr, 0, $offset, TRUE) + $inserted + array_slice($arr, $offset, count($arr), TRUE);
}
/**
* Renames key in array.
* @return void
*/
public static function renameKey(array & $arr, $oldKey, $newKey)
{
$offset = self::searchKey($arr, $oldKey);
if ($offset !== FALSE) {
$keys = array_keys($arr);
$keys[$offset] = $newKey;
$arr = array_combine($keys, $arr);
}
}
/**
* Returns array entries that match the pattern.
* @return array
*/
public static function grep(array $arr, $pattern, $flags = 0)
{
return Strings::pcre('preg_grep', [$pattern, $arr, $flags]);
}
/**
* Returns flattened array.
* @return array
*/
public static function flatten(array $arr, $preserveKeys = FALSE)
{
$res = [];
$cb = $preserveKeys
? function ($v, $k) use (& $res) { $res[$k] = $v; }
: function ($v) use (& $res) { $res[] = $v; };
array_walk_recursive($arr, $cb);
return $res;
}
/**
* Finds whether a variable is a zero-based integer indexed array.
* @return bool
*/
public static function isList($value)
{
return is_array($value) && (!$value || array_keys($value) === range(0, count($value) - 1));
}
/**
* Reformats table to associative tree. Path looks like 'field|field[]field->field=field'.
* @return array|\stdClass
*/
public static function associate(array $arr, $path)
{
$parts = is_array($path)
? $path
: preg_split('#(\[\]|->|=|\|)#', $path, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
if (!$parts || $parts[0] === '=' || $parts[0] === '|' || $parts === ['->']) {
throw new Nette\InvalidArgumentException("Invalid path '$path'.");
}
$res = $parts[0] === '->' ? new \stdClass : [];
foreach ($arr as $rowOrig) {
$row = (array) $rowOrig;
$x = & $res;
for ($i = 0; $i < count($parts); $i++) {
$part = $parts[$i];
if ($part === '[]') {
$x = & $x[];
} elseif ($part === '=') {
if (isset($parts[++$i])) {
$x = $row[$parts[$i]];
$row = NULL;
}
} elseif ($part === '->') {
if (isset($parts[++$i])) {
$x = & $x->{$row[$parts[$i]]};
} else {
$row = is_object($rowOrig) ? $rowOrig : (object) $row;
}
} elseif ($part !== '|') {
$x = & $x[(string) $row[$part]];
}
}
if ($x === NULL) {
$x = $row;
}
}
return $res;
}
/**
* Normalizes to associative array.
* @return array
*/
public static function normalize(array $arr, $filling = NULL)
{
$res = [];
foreach ($arr as $k => $v) {
$res[is_int($k) ? $v : $k] = is_int($k) ? $filling : $v;
}
return $res;
}
/**
* Picks element from the array by key and return its value.
* @param array
* @param string|int array key
* @param mixed
* @return mixed
* @throws Nette\InvalidArgumentException if item does not exist and default value is not provided
*/
public static function pick(array & $arr, $key, $default = NULL)
{
if (array_key_exists($key, $arr)) {
$value = $arr[$key];
unset($arr[$key]);
return $value;
} elseif (func_num_args() < 3) {
throw new Nette\InvalidArgumentException("Missing item '$key'.");
} else {
return $default;
}
}
}
Nette-2.4-20160731/Nette/Utils/ArrayList.php 0000644 0000000 0000000 00000004166 12747434604 016661 0 ustar root root list);
}
/**
* Returns items count.
* @return int
*/
public function count()
{
return count($this->list);
}
/**
* Replaces or appends a item.
* @param int|NULL
* @param mixed
* @return void
* @throws Nette\OutOfRangeException
*/
public function offsetSet($index, $value)
{
if ($index === NULL) {
$this->list[] = $value;
} elseif ($index < 0 || $index >= count($this->list)) {
throw new Nette\OutOfRangeException('Offset invalid or out of range');
} else {
$this->list[(int) $index] = $value;
}
}
/**
* Returns a item.
* @param int
* @return mixed
* @throws Nette\OutOfRangeException
*/
public function offsetGet($index)
{
if ($index < 0 || $index >= count($this->list)) {
throw new Nette\OutOfRangeException('Offset invalid or out of range');
}
return $this->list[(int) $index];
}
/**
* Determines whether a item exists.
* @param int
* @return bool
*/
public function offsetExists($index)
{
return $index >= 0 && $index < count($this->list);
}
/**
* Removes the element at the specified position in this list.
* @param int
* @return void
* @throws Nette\OutOfRangeException
*/
public function offsetUnset($index)
{
if ($index < 0 || $index >= count($this->list)) {
throw new Nette\OutOfRangeException('Offset invalid or out of range');
}
array_splice($this->list, (int) $index, 1);
}
/**
* Prepends a item.
* @param mixed
* @return void
*/
public function prepend($value)
{
$first = array_slice($this->list, 0, 1);
$this->offsetSet(0, $value);
array_splice($this->list, 1, 0, $first);
}
}
Nette-2.4-20160731/Nette/Utils/ArrayHash.php 0000644 0000000 0000000 00000003137 12747434604 016626 0 ustar root root $value) {
if ($recursive && is_array($value)) {
$obj->$key = static::from($value, TRUE);
} else {
$obj->$key = $value;
}
}
return $obj;
}
/**
* Returns an iterator over all items.
* @return \RecursiveArrayIterator
*/
public function getIterator()
{
return new \RecursiveArrayIterator((array) $this);
}
/**
* Returns items count.
* @return int
*/
public function count()
{
return count((array) $this);
}
/**
* Replaces or appends a item.
* @return void
*/
public function offsetSet($key, $value)
{
if (!is_scalar($key)) { // prevents NULL
throw new Nette\InvalidArgumentException(sprintf('Key must be either a string or an integer, %s given.', gettype($key)));
}
$this->$key = $value;
}
/**
* Returns a item.
* @return mixed
*/
public function offsetGet($key)
{
return $this->$key;
}
/**
* Determines whether a item exists.
* @return bool
*/
public function offsetExists($key)
{
return isset($this->$key);
}
/**
* Removes the element from this list.
* @return void
*/
public function offsetUnset($key)
{
unset($this->$key);
}
}
Nette-2.4-20160731/Nette/Tracy/ 0000755 0000000 0000000 00000000000 12747434604 014211 5 ustar root root Nette-2.4-20160731/Nette/Tracy/OutputDebugger.php 0000644 0000000 0000000 00000003515 12747434604 017673 0 ustar root root start();
}
public function start()
{
foreach (get_included_files() as $file) {
if (fread(fopen($file, 'r'), 3) === self::BOM) {
$this->list[] = [$file, 1, self::BOM];
}
}
ob_start([$this, 'handler'], 1);
}
/** @internal */
public function handler($s, $phase)
{
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
if (isset($trace[0]['file'], $trace[0]['line'])) {
$stack = $trace;
unset($stack[0]['line'], $stack[0]['args']);
$i = count($this->list);
if ($i && $this->list[$i - 1][3] === $stack) {
$this->list[$i - 1][2] .= $s;
} else {
$this->list[] = [$trace[0]['file'], $trace[0]['line'], $s, $stack];
}
}
if ($phase === PHP_OUTPUT_HANDLER_FINAL) {
return $this->renderHtml();
}
}
private function renderHtml()
{
$res = '';
foreach ($this->list as $item) {
$stack = [];
foreach (array_slice($item[3], 1) as $t) {
$t += ['class' => '', 'type' => '', 'function' => ''];
$stack[] = "$t[class]$t[type]$t[function]()"
. (isset($t['file'], $t['line']) ? ' in ' . basename($t['file']) . ":$t[line]" : '');
}
$res .= ''
. Helpers::editorLink($item[0], $item[1]) . ' '
. str_replace(self::BOM, 'BOM', Dumper::toHtml($item[2]))
. "
';
}
}
Nette-2.4-20160731/Nette/Tracy/Logger.php 0000644 0000000 0000000 00000012645 12747434604 016151 0 ustar root root directory = $directory;
$this->email = $email;
$this->blueScreen = $blueScreen;
$this->mailer = [$this, 'defaultMailer'];
}
/**
* Logs message or exception to file and sends email notification.
* @param string|\Exception|\Throwable
* @param int one of constant ILogger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email)
* @return string logged error filename
*/
public function log($message, $priority = self::INFO)
{
if (!$this->directory) {
throw new \LogicException('Directory is not specified.');
} elseif (!is_dir($this->directory)) {
throw new \RuntimeException("Directory '$this->directory' is not found or is not directory.");
}
$exceptionFile = $message instanceof \Exception || $message instanceof \Throwable
? $this->getExceptionFile($message)
: NULL;
$line = $this->formatLogLine($message, $exceptionFile);
$file = $this->directory . '/' . strtolower($priority ?: self::INFO) . '.log';
if (!@file_put_contents($file, $line . PHP_EOL, FILE_APPEND | LOCK_EX)) { // @ is escalated to exception
throw new \RuntimeException("Unable to write to log file '$file'. Is directory writable?");
}
if ($exceptionFile) {
$this->logException($message, $exceptionFile);
}
if (in_array($priority, [self::ERROR, self::EXCEPTION, self::CRITICAL], TRUE)) {
$this->sendEmail($message);
}
return $exceptionFile;
}
/**
* @param string|\Exception|\Throwable
* @return string
*/
protected function formatMessage($message)
{
if ($message instanceof \Exception || $message instanceof \Throwable) {
while ($message) {
$tmp[] = ($message instanceof \ErrorException
? Helpers::errorTypeToString($message->getSeverity()) . ': ' . $message->getMessage()
: Helpers::getClass($message) . ': ' . $message->getMessage()
) . ' in ' . $message->getFile() . ':' . $message->getLine();
$message = $message->getPrevious();
}
$message = implode($tmp, "\ncaused by ");
} elseif (!is_string($message)) {
$message = Dumper::toText($message);
}
return trim($message);
}
/**
* @param string|\Exception|\Throwable
* @return string
*/
protected function formatLogLine($message, $exceptionFile = NULL)
{
return implode(' ', [
@date('[Y-m-d H-i-s]'), // @ timezone may not be set
preg_replace('#\s*\r?\n\s*#', ' ', $this->formatMessage($message)),
' @ ' . Helpers::getSource(),
$exceptionFile ? ' @@ ' . basename($exceptionFile) : NULL,
]);
}
/**
* @param \Exception|\Throwable
* @return string
*/
public function getExceptionFile($exception)
{
$dir = strtr($this->directory . '/', '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR);
$hash = substr(md5(preg_replace('~(Resource id #)\d+~', '$1', $exception)), 0, 10);
foreach (new \DirectoryIterator($this->directory) as $file) {
if (strpos($file, $hash)) {
return $dir . $file;
}
}
return $dir . 'exception--' . @date('Y-m-d--H-i') . "--$hash.html"; // @ timezone may not be set
}
/**
* Logs exception to the file if file doesn't exist.
* @param \Exception|\Throwable
* @return string logged error filename
*/
protected function logException($exception, $file = NULL)
{
$file = $file ?: $this->getExceptionFile($exception);
$bs = $this->blueScreen ?: new BlueScreen;
$bs->renderToFile($exception, $file);
return $file;
}
/**
* @param string|\Exception|\Throwable
* @return void
*/
protected function sendEmail($message)
{
$snooze = is_numeric($this->emailSnooze)
? $this->emailSnooze
: @strtotime($this->emailSnooze) - time(); // @ timezone may not be set
if ($this->email && $this->mailer
&& @filemtime($this->directory . '/email-sent') + $snooze < time() // @ file may not exist
&& @file_put_contents($this->directory . '/email-sent', 'sent') // @ file may not be writable
) {
call_user_func($this->mailer, $message, implode(', ', (array) $this->email));
}
}
/**
* Default mailer.
* @param string|\Exception|\Throwable
* @param string
* @return void
* @internal
*/
public function defaultMailer($message, $email)
{
$host = preg_replace('#[^\w.-]+#', '', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n'));
$parts = str_replace(
["\r\n", "\n"],
["\n", PHP_EOL],
[
'headers' => implode("\n", [
'From: ' . ($this->fromEmail ?: "noreply@$host"),
'X-Mailer: Tracy',
'Content-Type: text/plain; charset=UTF-8',
'Content-Transfer-Encoding: 8bit',
]) . "\n",
'subject' => "PHP: An error occurred on the server $host",
'body' => $this->formatMessage($message) . "\n\nsource: " . Helpers::getSource(),
]
);
mail($email, $parts['subject'], $parts['body'], $parts['headers']);
}
}
Nette-2.4-20160731/Nette/Tracy/ILogger.php 0000644 0000000 0000000 00000000575 12747434604 016261 0 ustar root root strlen($m[0])) {
$file = '...' . $m[0];
}
$file = strtr($file, '/', DIRECTORY_SEPARATOR);
return self::formatHtml('%%%',
$editor,
$file . ($line ? ":$line" : ''),
rtrim(dirname($file), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR,
basename($file),
$line ? ":$line" : ''
);
} else {
return self::formatHtml('%', $file . ($line ? ":$line" : ''));
}
}
/**
* Returns link to editor.
* @return string
*/
public static function editorUri($file, $line = NULL)
{
if (Debugger::$editor && $file && is_file($file)) {
$file = strtr($file, Debugger::$editorMapping);
return strtr(Debugger::$editor, ['%file' => rawurlencode($file), '%line' => $line ? (int) $line : 1]);
}
}
public static function formatHtml($mask)
{
$args = func_get_args();
return preg_replace_callback('#%#', function () use (& $args, & $count) {
return Helpers::escapeHtml($args[++$count]);
}, $mask);
}
public static function escapeHtml($s)
{
return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
public static function findTrace(array $trace, $method, & $index = NULL)
{
$m = explode('::', $method);
foreach ($trace as $i => $item) {
if (isset($item['function']) && $item['function'] === end($m)
&& isset($item['class']) === isset($m[1])
&& (!isset($item['class']) || $m[0] === '*' || is_a($item['class'], $m[0], TRUE))
) {
$index = $i;
return $item;
}
}
}
/**
* @return string
*/
public static function getClass($obj)
{
return explode("\x00", get_class($obj))[0];
}
/** @internal */
public static function fixStack($exception)
{
if (function_exists('xdebug_get_function_stack')) {
$stack = [];
foreach (array_slice(array_reverse(xdebug_get_function_stack()), 2, -1) as $row) {
$frame = [
'file' => $row['file'],
'line' => $row['line'],
'function' => isset($row['function']) ? $row['function'] : '*unknown*',
'args' => [],
];
if (!empty($row['class'])) {
$frame['type'] = isset($row['type']) && $row['type'] === 'dynamic' ? '->' : '::';
$frame['class'] = $row['class'];
}
$stack[] = $frame;
}
$ref = new \ReflectionProperty('Exception', 'trace');
$ref->setAccessible(TRUE);
$ref->setValue($exception, $stack);
}
return $exception;
}
/** @internal */
public static function fixEncoding($s)
{
return htmlspecialchars_decode(htmlspecialchars($s, ENT_NOQUOTES | ENT_IGNORE, 'UTF-8'), ENT_NOQUOTES);
}
/** @internal */
public static function errorTypeToString($type)
{
$types = [
E_ERROR => 'Fatal Error',
E_USER_ERROR => 'User Error',
E_RECOVERABLE_ERROR => 'Recoverable Error',
E_CORE_ERROR => 'Core Error',
E_COMPILE_ERROR => 'Compile Error',
E_PARSE => 'Parse Error',
E_WARNING => 'Warning',
E_CORE_WARNING => 'Core Warning',
E_COMPILE_WARNING => 'Compile Warning',
E_USER_WARNING => 'User Warning',
E_NOTICE => 'Notice',
E_USER_NOTICE => 'User Notice',
E_STRICT => 'Strict standards',
E_DEPRECATED => 'Deprecated',
E_USER_DEPRECATED => 'User Deprecated',
];
return isset($types[$type]) ? $types[$type] : 'Unknown error';
}
/** @internal */
public static function getSource()
{
if (isset($_SERVER['REQUEST_URI'])) {
return (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://')
. (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '')
. $_SERVER['REQUEST_URI'];
} else {
return 'CLI (PID: ' . getmypid() . ')'
. (empty($_SERVER['argv']) ? '' : ': ' . implode(' ', $_SERVER['argv']));
}
}
/** @internal */
public static function improveException($e)
{
$message = $e->getMessage();
if (!$e instanceof \Error && !$e instanceof \ErrorException) {
// do nothing
} elseif (preg_match('#^Call to undefined function (\S+\\\\)?(\w+)\(#', $message, $m)) {
$funcs = array_merge(get_defined_functions()['internal'], get_defined_functions()['user']);
$hint = self::getSuggestion($funcs, $m[1] . $m[2]) ?: self::getSuggestion($funcs, $m[2]);
$message .= ", did you mean $hint()?";
} elseif (preg_match('#^Call to undefined method (\S+)::(\w+)#', $message, $m)) {
$hint = self::getSuggestion(get_class_methods($m[1]), $m[2]);
$message .= ", did you mean $hint()?";
} elseif (preg_match('#^Undefined variable: (\w+)#', $message, $m) && !empty($e->context)) {
$hint = self::getSuggestion(array_keys($e->context), $m[1]);
$message = "Undefined variable $$m[1], did you mean $$hint?";
} elseif (preg_match('#^Undefined property: (\S+)::\$(\w+)#', $message, $m)) {
$rc = new \ReflectionClass($m[1]);
$items = array_diff($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
$hint = self::getSuggestion($items, $m[2]);
$message .= ", did you mean $$hint?";
} elseif (preg_match('#^Access to undeclared static property: (\S+)::\$(\w+)#', $message, $m)) {
$rc = new \ReflectionClass($m[1]);
$items = array_intersect($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
$hint = self::getSuggestion($items, $m[2]);
$message .= ", did you mean $$hint?";
}
if (isset($hint)) {
$ref = new \ReflectionProperty($e, 'message');
$ref->setAccessible(TRUE);
$ref->setValue($e, $message);
}
}
/**
* Finds the best suggestion.
* @return string|NULL
* @internal
*/
public static function getSuggestion(array $items, $value)
{
$best = NULL;
$min = (strlen($value) / 4 + 1) * 10 + .1;
foreach (array_unique($items, SORT_REGULAR) as $item) {
$item = is_object($item) ? $item->getName() : $item;
if (($len = levenshtein($item, $value, 10, 11, 10)) > 0 && $len < $min) {
$min = $len;
$best = $item;
}
}
return $best;
}
/** @internal */
public static function isHtmlMode()
{
return empty($_SERVER['HTTP_X_REQUESTED_WITH']) && empty($_SERVER['HTTP_X_TRACY_AJAX'])
&& PHP_SAPI !== 'cli'
&& !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list()));
}
/** @internal */
public static function isAjax()
{
return isset($_SERVER['HTTP_X_TRACY_AJAX']) && preg_match('#^\w{10}\z#', $_SERVER['HTTP_X_TRACY_AJAX']);
}
}
Nette-2.4-20160731/Nette/Tracy/FireLogger.php 0000644 0000000 0000000 00000011106 12747434604 016746 0 ustar root root []];
/**
* Sends message to FireLogger console.
* @param mixed
* @return bool was successful?
*/
public function log($message, $priority = self::DEBUG)
{
if (!isset($_SERVER['HTTP_X_FIRELOGGER']) || headers_sent()) {
return FALSE;
}
$item = [
'name' => 'PHP',
'level' => $priority,
'order' => count($this->payload['logs']),
'time' => str_pad(number_format((microtime(TRUE) - Debugger::$time) * 1000, 1, '.', ' '), 8, '0', STR_PAD_LEFT) . ' ms',
'template' => '',
'message' => '',
'style' => 'background:#767ab6',
];
$args = func_get_args();
if (isset($args[0]) && is_string($args[0])) {
$item['template'] = array_shift($args);
}
if (isset($args[0]) && ($args[0] instanceof \Exception || $args[0] instanceof \Throwable)) {
$e = array_shift($args);
$trace = $e->getTrace();
if (isset($trace[0]['class']) && $trace[0]['class'] === 'Tracy\Debugger'
&& ($trace[0]['function'] === 'shutdownHandler' || $trace[0]['function'] === 'errorHandler')
) {
unset($trace[0]);
}
$file = str_replace(dirname(dirname(dirname($e->getFile()))), "\xE2\x80\xA6", $e->getFile());
$item['template'] = ($e instanceof \ErrorException ? '' : Helpers::getClass($e) . ': ')
. $e->getMessage() . ($e->getCode() ? ' #' . $e->getCode() : '') . ' in ' . $file . ':' . $e->getLine();
$item['pathname'] = $e->getFile();
$item['lineno'] = $e->getLine();
} else {
$trace = debug_backtrace();
if (isset($trace[1]['class']) && $trace[1]['class'] === 'Tracy\Debugger'
&& ($trace[1]['function'] === 'fireLog')
) {
unset($trace[0]);
}
foreach ($trace as $frame) {
if (isset($frame['file']) && is_file($frame['file'])) {
$item['pathname'] = $frame['file'];
$item['lineno'] = $frame['line'];
break;
}
}
}
$item['exc_info'] = ['', '', []];
$item['exc_frames'] = [];
foreach ($trace as $frame) {
$frame += ['file' => NULL, 'line' => NULL, 'class' => NULL, 'type' => NULL, 'function' => NULL, 'object' => NULL, 'args' => NULL];
$item['exc_info'][2][] = [$frame['file'], $frame['line'], "$frame[class]$frame[type]$frame[function]", $frame['object']];
$item['exc_frames'][] = $frame['args'];
}
if (isset($args[0]) && in_array($args[0], [self::DEBUG, self::INFO, self::WARNING, self::ERROR, self::CRITICAL], TRUE)) {
$item['level'] = array_shift($args);
}
$item['args'] = $args;
$this->payload['logs'][] = $this->jsonDump($item, -1);
foreach (str_split(base64_encode(json_encode($this->payload)), 4990) as $k => $v) {
header("FireLogger-de11e-$k:$v");
}
return TRUE;
}
/**
* Dump implementation for JSON.
* @param mixed variable to dump
* @param int current recursion level
* @return string
*/
private function jsonDump(& $var, $level = 0)
{
if (is_bool($var) || is_null($var) || is_int($var) || is_float($var)) {
return $var;
} elseif (is_string($var)) {
return Dumper::encodeString($var, $this->maxLength);
} elseif (is_array($var)) {
static $marker;
if ($marker === NULL) {
$marker = uniqid("\x00", TRUE);
}
if (isset($var[$marker])) {
return "\xE2\x80\xA6RECURSION\xE2\x80\xA6";
} elseif ($level < $this->maxDepth || !$this->maxDepth) {
$var[$marker] = TRUE;
$res = [];
foreach ($var as $k => & $v) {
if ($k !== $marker) {
$res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1);
}
}
unset($var[$marker]);
return $res;
} else {
return " \xE2\x80\xA6 ";
}
} elseif (is_object($var)) {
$arr = (array) $var;
static $list = [];
if (in_array($var, $list, TRUE)) {
return "\xE2\x80\xA6RECURSION\xE2\x80\xA6";
} elseif ($level < $this->maxDepth || !$this->maxDepth) {
$list[] = $var;
$res = ["\x00" => '(object) ' . Helpers::getClass($var)];
foreach ($arr as $k => & $v) {
if (isset($k[0]) && $k[0] === "\x00") {
$k = substr($k, strrpos($k, "\x00") + 1);
}
$res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1);
}
array_pop($list);
return $res;
} else {
return " \xE2\x80\xA6 ";
}
} elseif (is_resource($var)) {
return 'resource ' . get_resource_type($var);
} else {
return 'unknown type';
}
}
}
Nette-2.4-20160731/Nette/Tracy/Dumper.php 0000644 0000000 0000000 00000041217 12747434604 016163 0 ustar root root '1;33',
'null' => '1;33',
'number' => '1;32',
'string' => '1;36',
'array' => '1;31',
'key' => '1;37',
'object' => '1;31',
'visibility' => '1;30',
'resource' => '1;37',
'indent' => '1;30',
];
/** @var array */
public static $resources = [
'stream' => 'stream_get_meta_data',
'stream-context' => 'stream_context_get_options',
'curl' => 'curl_getinfo',
];
/** @var array */
public static $objectExporters = [
'Closure' => 'Tracy\Dumper::exportClosure',
'SplFileInfo' => 'Tracy\Dumper::exportSplFileInfo',
'SplObjectStorage' => 'Tracy\Dumper::exportSplObjectStorage',
'__PHP_Incomplete_Class' => 'Tracy\Dumper::exportPhpIncompleteClass',
];
/** @var string @internal */
public static $livePrefix;
/** @var array */
private static $liveStorage = [];
/**
* Dumps variable to the output.
* @return mixed variable
*/
public static function dump($var, array $options = NULL)
{
if (PHP_SAPI !== 'cli' && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list()))) {
echo self::toHtml($var, $options);
} elseif (self::detectColors()) {
echo self::toTerminal($var, $options);
} else {
echo self::toText($var, $options);
}
return $var;
}
/**
* Dumps variable to HTML.
* @return string
*/
public static function toHtml($var, array $options = NULL)
{
$options = (array) $options + [
self::DEPTH => 4,
self::TRUNCATE => 150,
self::COLLAPSE => 14,
self::COLLAPSE_COUNT => 7,
self::OBJECT_EXPORTERS => NULL,
];
$loc = & $options[self::LOCATION];
$loc = $loc === TRUE ? ~0 : (int) $loc;
$options[self::OBJECT_EXPORTERS] = (array) $options[self::OBJECT_EXPORTERS] + self::$objectExporters;
uksort($options[self::OBJECT_EXPORTERS], function ($a, $b) {
return $b === '' || (class_exists($a, FALSE) && is_subclass_of($a, $b)) ? -1 : 1;
});
$live = !empty($options[self::LIVE]) && $var && (is_array($var) || is_object($var) || is_resource($var));
list($file, $line, $code) = $loc ? self::findLocation() : NULL;
$locAttrs = $file && $loc & self::LOCATION_SOURCE ? Helpers::formatHtml(
' title="%in file % on line %" data-tracy-href="%"', "$code\n", $file, $line, Helpers::editorUri($file, $line)
) : NULL;
return '
\n";
}
return $res . '
" : '>') . ($live ? '' : self::dumpVar($var, $options)) . ($file && $loc & self::LOCATION_LINK ? 'in ' . Helpers::editorLink($file, $line) . '' : '') . "\n"; } /** * Dumps variable to plain text. * @return string */ public static function toText($var, array $options = NULL) { return htmlspecialchars_decode(strip_tags(self::toHtml($var, $options)), ENT_QUOTES); } /** * Dumps variable to x-terminal. * @return string */ public static function toTerminal($var, array $options = NULL) { return htmlspecialchars_decode(strip_tags(preg_replace_callback('#|#', function ($m) { return "\033[" . (isset($m[1], self::$terminalColors[$m[1]]) ? self::$terminalColors[$m[1]] : '0') . 'm'; }, self::toHtml($var, $options))), ENT_QUOTES); } /** * Internal toHtml() dump implementation. * @param mixed variable to dump * @param array options * @param int current recursion level * @return string */ private static function dumpVar(& $var, array $options, $level = 0) { if (method_exists(__CLASS__, $m = 'dump' . gettype($var))) { return self::$m($var, $options, $level); } else { return "unknown type\n"; } } private static function dumpNull() { return "NULL\n"; } private static function dumpBoolean(& $var) { return '' . ($var ? 'TRUE' : 'FALSE') . "\n"; } private static function dumpInteger(& $var) { return "$var\n"; } private static function dumpDouble(& $var) { $var = is_finite($var) ? ($tmp = json_encode($var)) . (strpos($tmp, '.') === FALSE ? '.0' : '') : str_replace('.0', '', var_export($var, TRUE)); // workaround for PHP 7.0.2 return "$var\n"; } private static function dumpString(& $var, $options) { return '"' . Helpers::escapeHtml(self::encodeString($var, $options[self::TRUNCATE])) . '"' . (strlen($var) > 1 ? ' (' . strlen($var) . ')' : '') . "\n"; } private static function dumpArray(& $var, $options, $level) { static $marker; if ($marker === NULL) { $marker = uniqid("\x00", TRUE); } $out = 'array ('; if (empty($var)) { return $out . ")\n"; } elseif (isset($var[$marker])) { return $out . (count($var) - 1) . ") [ RECURSION ]\n"; } elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH]) { $collapsed = $level ? count($var) >= $options[self::COLLAPSE_COUNT] : (is_int($options[self::COLLAPSE]) ? count($var) >= $options[self::COLLAPSE] : $options[self::COLLAPSE]); $out = '' . $out . count($var) . ")\n
$source = str_replace('
', "\n", $source[1]);
$out .= static::highlightLine($source, $line, $lines);
if ($vars) {
$out = preg_replace_callback('#">\$(\w+)( )?#', function ($m) use ($vars) {
return array_key_exists($m[1], $vars)
? '" title="'
. str_replace('"', '"', trim(strip_tags(Dumper::toHtml($vars[$m[1]], [Dumper::DEPTH => 1]))))
. $m[0]
: $m[0];
}, $out);
}
$out = str_replace(' ', ' ', $out);
return "$out
";
}
/**
* Returns highlighted line in HTML code.
* @return string
*/
public static function highlightLine($html, $line, $lines = 15)
{
$source = explode("\n", "\n" . str_replace("\r\n", "\n", $html));
$out = '';
$spans = 1;
$start = $i = max(1, min($line, count($source) - 1) - floor($lines * 2 / 3));
while (--$i >= 1) { // find last highlighted block
if (preg_match('#.*(?span[^>]*>)#', $source[$i], $m)) {
if ($m[1] !== '') {
$spans++;
$out .= $m[1];
}
break;
}
}
$source = array_slice($source, $start, $lines, TRUE);
end($source);
$numWidth = strlen((string) key($source));
foreach ($source as $n => $s) {
$spans += substr_count($s, ']+>#', $s, $tags);
if ($n == $line) {
$out .= sprintf(
"%{$numWidth}s: %s\n%s",
$n,
strip_tags($s),
implode('', $tags[0])
);
} else {
$out .= sprintf("%{$numWidth}s: %s\n", $n, $s);
}
}
$out .= str_repeat('', $spans) . '
';
return $out;
}
/**
* Should a file be collapsed in stack trace?
* @param string
* @return bool
*/
public function isCollapsed($file)
{
$file = strtr($file, '\\', '/') . '/';
foreach ($this->collapsePaths as $path) {
$path = strtr($path, '\\', '/') . '/';
if (strncmp($file, $path, strlen($path)) === 0) {
return TRUE;
}
}
return FALSE;
}
}
Nette-2.4-20160731/Nette/Tracy/Bar.php 0000644 0000000 0000000 00000014427 12747434604 015436 0 ustar root root panels[$id]));
}
$this->panels[$id] = $panel;
return $this;
}
/**
* Returns panel with given id
* @param string
* @return IBarPanel|NULL
*/
public function getPanel($id)
{
return isset($this->panels[$id]) ? $this->panels[$id] : NULL;
}
/**
* Renders debug bar.
* @return void
*/
public function render()
{
$useSession = $this->dispatched && session_status() === PHP_SESSION_ACTIVE;
$redirectQueue = & $_SESSION['_tracy']['redirect'];
if (!Helpers::isHtmlMode() && !Helpers::isAjax()) {
return;
} elseif (Helpers::isAjax()) {
$rows[] = (object) ['type' => 'ajax', 'panels' => $this->renderPanels('-ajax')];
$dumps = Dumper::fetchLiveData();
$contentId = $useSession ? $_SERVER['HTTP_X_TRACY_AJAX'] . '-ajax' : NULL;
} elseif (preg_match('#^Location:#im', implode("\n", headers_list()))) { // redirect
$redirectQueue = array_slice((array) $redirectQueue, -10);
Dumper::fetchLiveData();
Dumper::$livePrefix = count($redirectQueue) . 'p';
$redirectQueue[] = [
'panels' => $this->renderPanels('-r' . count($redirectQueue)),
'dumps' => Dumper::fetchLiveData(),
];
return;
} else {
$rows[] = (object) ['type' => 'main', 'panels' => $this->renderPanels()];
$dumps = Dumper::fetchLiveData();
foreach (array_reverse((array) $redirectQueue) as $info) {
$rows[] = (object) ['type' => 'redirect', 'panels' => $info['panels']];
$dumps += $info['dumps'];
}
$redirectQueue = NULL;
$contentId = $useSession ? substr(md5(uniqid('', TRUE)), 0, 10) : NULL;
}
ob_start(function () {});
require __DIR__ . '/assets/Bar/panels.phtml';
require __DIR__ . '/assets/Bar/bar.phtml';
$content = Helpers::fixEncoding(ob_get_clean());
if ($contentId) {
$queue = & $_SESSION['_tracy']['bar'];
$queue = array_slice(array_filter((array) $queue), -5, NULL, TRUE);
$queue[$contentId] = ['content' => $content, 'dumps' => $dumps];
}
if (Helpers::isHtmlMode()) {
$stopXdebug = extension_loaded('xdebug') ? ['XDEBUG_SESSION_STOP' => 1, 'XDEBUG_PROFILE' => 0, 'XDEBUG_TRACE' => 0] : [];
$path = isset($_SERVER['REQUEST_URI']) ? explode('?', $_SERVER['REQUEST_URI'])[0] : '/';
$lpath = strtolower($path);
$script = isset($_SERVER['SCRIPT_NAME']) ? strtolower($_SERVER['SCRIPT_NAME']) : '';
if ($lpath !== $script) {
$max = min(strlen($lpath), strlen($script));
for ($i = 0; $i < $max && $lpath[$i] === $script[$i]; $i++);
$path = $i ? substr($path, 0, strrpos($path, '/', $i - strlen($path) - 1) + 1) : '/';
$cookiePath = session_get_cookie_params()['path'];
if (substr($cookiePath, 0, strlen($path)) === $path) {
$path = rtrim($cookiePath, '/') . '/';
}
}
require __DIR__ . '/assets/Bar/loader.phtml';
}
}
/**
* @return array
*/
private function renderPanels($suffix = NULL)
{
set_error_handler(function ($severity, $message, $file, $line) {
if (error_reporting() & $severity) {
throw new \ErrorException($message, 0, $severity, $file, $line);
}
});
$obLevel = ob_get_level();
$panels = [];
foreach ($this->panels as $id => $panel) {
$idHtml = preg_replace('#[^a-z0-9]+#i', '-', $id) . $suffix;
try {
$tab = (string) $panel->getTab();
$panelHtml = $tab ? (string) $panel->getPanel() : NULL;
if ($tab && $panel instanceof \Nette\Diagnostics\IBarPanel) {
$e = new \Exception('Support for Nette\Diagnostics\IBarPanel is deprecated');
}
} catch (\Throwable $e) {
} catch (\Exception $e) {
}
if (isset($e)) {
while (ob_get_level() > $obLevel) { // restore ob-level if broken
ob_end_clean();
}
$idHtml = "error-$idHtml";
$tab = "Error in $id";
$panelHtml = "We're sorry! The server encountered an internal error and was unable to complete your request. Please try again later.
error 500
Tracy is unable to log error.
= Helpers::escapeHtml($title . $code) ?>
File: = Helpers::editorLink($ex->getFile(), $ex->getLine()) ?>
getFile())): ?>= self::highlightFile($ex->getFile(), $ex->getLine(), 15, $ex instanceof \ErrorException && isset($ex->context) ? $ex->context : NULL) ?>= Helpers::editorLink($row['file'], $row['line']) ?> inner-code source "; if (isset($row['class'])) echo Helpers::escapeHtml($row['class'] . $row['type']); if (isset($row['object'])) echo ''; echo Helpers::escapeHtml($row['function']), '('; if (!empty($row['args'])): ?>arguments)
', Helpers::escapeHtml(isset($params[$k]) ? '$' . $params[$k]->name : "#$k"), ' | '; echo $dump($v); echo " |
---|
$', Helpers::escapeHtml($k), ' | ', $dump($v), " |
---|
= Helpers::editorLink($lastError['file'], $lastError['line']) ?>
inner-code
', Helpers::escapeHtml($k), ' | ', $dump($v), " |
---|
empty
', Helpers::escapeHtml($k), ' | ', $k === '__NF' ? 'Nette Session' : $dump($v), " |
---|
', Helpers::escapeHtml($k), ' | ', $dump($v), " |
---|
', Helpers::escapeHtml($k), ' | '; echo '', $dump($v), " |
---|