mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-04-17 09:24:17 +09:00
Merge pull request #385 from kijin/pr/more-framework-classes
Rhymix Framework 각종 기능 추가
This commit is contained in:
commit
321015e050
269 changed files with 38164 additions and 616 deletions
|
|
@ -686,7 +686,7 @@ class Context
|
|||
public function checkSSO()
|
||||
{
|
||||
// pass if it's not GET request or XE is not yet installed
|
||||
if(!config('use_sso') || isCrawler())
|
||||
if(!config('use_sso') || Rhymix\Framework\UA::isRobot())
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
class FileHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Changes path of target file, directory into absolute path
|
||||
*
|
||||
|
|
@ -17,12 +16,7 @@ class FileHandler
|
|||
*/
|
||||
public static function getRealPath($source)
|
||||
{
|
||||
if(strlen($source) >= 2 && substr_compare($source, './', 0, 2) === 0)
|
||||
{
|
||||
return _XE_PATH_ . substr($source, 2);
|
||||
}
|
||||
|
||||
return $source;
|
||||
return (strncmp($source, './', 2) === 0) ? (\RX_BASEDIR . substr($source, 2)) : $source;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -33,64 +27,11 @@ class FileHandler
|
|||
* @param string $source_dir Path of source directory
|
||||
* @param string $target_dir Path of target dir
|
||||
* @param string $filter Regex to filter files. If file matches this regex, the file is not copied.
|
||||
* @param string $type If set as 'force'. Even if the file exists in target, the file is copied.
|
||||
* @return void
|
||||
*/
|
||||
public static function copyDir($source_dir, $target_dir, $filter = null, $type = null)
|
||||
public static function copyDir($source_dir, $target_dir, $filter = null)
|
||||
{
|
||||
$source_dir = self::getRealPath($source_dir);
|
||||
$target_dir = self::getRealPath($target_dir);
|
||||
if(!is_dir($source_dir))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// generate when no target exists
|
||||
self::makeDir($target_dir);
|
||||
|
||||
if(substr($source_dir, -1) != DIRECTORY_SEPARATOR)
|
||||
{
|
||||
$source_dir .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
if(substr($target_dir, -1) != DIRECTORY_SEPARATOR)
|
||||
{
|
||||
$target_dir .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
$oDir = dir($source_dir);
|
||||
while($file = $oDir->read())
|
||||
{
|
||||
if($file{0} == '.')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if($filter && preg_match($filter, $file))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(is_dir($source_dir . $file))
|
||||
{
|
||||
self::copyDir($source_dir . $file, $target_dir . $file, $type);
|
||||
}
|
||||
else
|
||||
{
|
||||
if($type == 'force')
|
||||
{
|
||||
@unlink($target_dir . $file);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!file_exists($target_dir . $file))
|
||||
{
|
||||
@copy($source_dir . $file, $target_dir . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$oDir->close();
|
||||
return Rhymix\Framework\Storage::copyDirectory(self::getRealPath($source_dir), self::getRealPath($target_dir), $filter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -104,18 +45,7 @@ class FileHandler
|
|||
public static function copyFile($source, $target, $force = 'Y')
|
||||
{
|
||||
setlocale(LC_CTYPE, 'en_US.UTF8', 'ko_KR.UTF8');
|
||||
$source = self::getRealPath($source);
|
||||
$target_dir = self::getRealPath(dirname($target));
|
||||
$target = basename($target);
|
||||
|
||||
self::makeDir($target_dir);
|
||||
|
||||
if($force == 'Y')
|
||||
{
|
||||
@unlink($target_dir . DIRECTORY_SEPARATOR . $target);
|
||||
}
|
||||
|
||||
@copy($source, $target_dir . DIRECTORY_SEPARATOR . $target);
|
||||
return Rhymix\Framework\Storage::copy(self::getRealPath($source), self::getRealPath($target));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -126,12 +56,7 @@ class FileHandler
|
|||
*/
|
||||
public static function readFile($filename)
|
||||
{
|
||||
if(($filename = self::exists($filename)) === FALSE || filesize($filename) < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return @file_get_contents($filename);
|
||||
return Rhymix\Framework\Storage::read(self::getRealPath($filename));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -144,22 +69,7 @@ class FileHandler
|
|||
*/
|
||||
public static function writeFile($filename, $buff, $mode = "w")
|
||||
{
|
||||
$filename = self::getRealPath($filename);
|
||||
$pathinfo = pathinfo($filename);
|
||||
self::makeDir($pathinfo['dirname']);
|
||||
|
||||
$flags = 0;
|
||||
if(strtolower($mode) == 'a')
|
||||
{
|
||||
$flags = FILE_APPEND;
|
||||
}
|
||||
|
||||
@file_put_contents($filename, $buff, $flags|LOCK_EX);
|
||||
@chmod($filename, 0644);
|
||||
if(function_exists('opcache_invalidate') && substr($filename, -4) === '.php')
|
||||
{
|
||||
@opcache_invalidate($filename, true);
|
||||
}
|
||||
return Rhymix\Framework\Storage::write(self::getRealPath($filename), $buff, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -170,16 +80,7 @@ class FileHandler
|
|||
*/
|
||||
public static function removeFile($filename)
|
||||
{
|
||||
if(($filename = self::exists($filename)) === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$status = @unlink($filename);
|
||||
if(function_exists('opcache_invalidate') && substr($filename, -4) === '.php')
|
||||
{
|
||||
@opcache_invalidate($filename, true);
|
||||
}
|
||||
return $status;
|
||||
return Rhymix\Framework\Storage::delete(self::getRealPath($filename));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -193,7 +94,7 @@ class FileHandler
|
|||
*/
|
||||
public static function rename($source, $target)
|
||||
{
|
||||
return @rename(self::getRealPath($source), self::getRealPath($target));
|
||||
return Rhymix\Framework\Storage::move(self::getRealPath($source), self::getRealPath($target));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -205,12 +106,7 @@ class FileHandler
|
|||
*/
|
||||
public static function moveFile($source, $target)
|
||||
{
|
||||
if(($source = self::exists($source)) !== FALSE)
|
||||
{
|
||||
self::removeFile($target);
|
||||
return self::rename($source, $target);
|
||||
}
|
||||
return FALSE;
|
||||
return Rhymix\Framework\Storage::move(self::getRealPath($source), self::getRealPath($target));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -224,7 +120,7 @@ class FileHandler
|
|||
*/
|
||||
public static function moveDir($source_dir, $target_dir)
|
||||
{
|
||||
self::rename($source_dir, $target_dir);
|
||||
return Rhymix\Framework\Storage::move(self::getRealPath($source_dir), self::getRealPath($target_dir));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -240,45 +136,31 @@ class FileHandler
|
|||
*/
|
||||
public static function readDir($path, $filter = '', $to_lower = FALSE, $concat_prefix = FALSE)
|
||||
{
|
||||
$path = self::getRealPath($path);
|
||||
$list = Rhymix\Framework\Storage::readDirectory(self::getRealPath($path), $concat_prefix, true, false);
|
||||
if (!$list)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
$output = array();
|
||||
|
||||
if(substr($path, -1) != '/')
|
||||
foreach ($list as $filename)
|
||||
{
|
||||
$path .= '/';
|
||||
}
|
||||
|
||||
if(!is_dir($path))
|
||||
{
|
||||
return $output;
|
||||
}
|
||||
|
||||
$files = scandir($path);
|
||||
foreach($files as $file)
|
||||
{
|
||||
if($file{0} == '.' || ($filter && !preg_match($filter, $file)))
|
||||
$filename = str_replace(array('/\\', '//'), '/', $filename);
|
||||
$basename = $concat_prefix ? basename($filename) : $filename;
|
||||
if ($basename[0] === '.' || ($filter && !preg_match($filter, $basename)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if($to_lower)
|
||||
if ($to_lower)
|
||||
{
|
||||
$file = strtolower($file);
|
||||
$filename = strtolower($filename);
|
||||
}
|
||||
|
||||
if($filter)
|
||||
{
|
||||
$file = preg_replace($filter, '$1', $file);
|
||||
$filename = preg_replace($filter, '$1', $filename);
|
||||
}
|
||||
|
||||
if($concat_prefix)
|
||||
{
|
||||
$file = sprintf('%s%s', str_replace(_XE_PATH_, '', $path), $file);
|
||||
}
|
||||
|
||||
$output[] = str_replace(array('/\\', '//'), '/', $file);
|
||||
$output[] = $filename;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -292,16 +174,11 @@ class FileHandler
|
|||
*/
|
||||
public static function makeDir($path_string)
|
||||
{
|
||||
if(self::exists($path_string) !== FALSE)
|
||||
if (!ini_get('safe_mode'))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(!ini_get('safe_mode'))
|
||||
{
|
||||
@mkdir($path_string, 0755, TRUE);
|
||||
@chmod($path_string, 0755);
|
||||
return Rhymix\Framework\Storage::createDirectory(self::getRealPath($path_string));
|
||||
}
|
||||
|
||||
// if safe_mode is on, use FTP
|
||||
else
|
||||
{
|
||||
|
|
@ -372,37 +249,7 @@ class FileHandler
|
|||
*/
|
||||
public static function removeDir($path)
|
||||
{
|
||||
if(($path = self::isDir($path)) === FALSE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(self::isDir($path))
|
||||
{
|
||||
$files = array_diff(scandir($path), array('..', '.'));
|
||||
|
||||
foreach($files as $file)
|
||||
{
|
||||
if(($target = self::getRealPath($path . DIRECTORY_SEPARATOR . $file)) === FALSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(is_dir($target))
|
||||
{
|
||||
self::removeDir($target);
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink($target);
|
||||
}
|
||||
}
|
||||
rmdir($path);
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink($path);
|
||||
}
|
||||
return Rhymix\Framework\Storage::deleteDirectory(self::getRealPath($path));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -413,27 +260,14 @@ class FileHandler
|
|||
*/
|
||||
public static function removeBlankDir($path)
|
||||
{
|
||||
if(($path = self::isDir($path)) === FALSE)
|
||||
$path = self::getRealPath($path);
|
||||
if (Rhymix\Framework\Storage::isEmptyDirectory($path))
|
||||
{
|
||||
return;
|
||||
return Rhymix\Framework\Storage::deleteDirectory($path);
|
||||
}
|
||||
|
||||
$files = array_diff(scandir($path), array('..', '.'));
|
||||
|
||||
if(count($files) < 1)
|
||||
else
|
||||
{
|
||||
rmdir($path);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($files as $file)
|
||||
{
|
||||
if(($target = self::isDir($path . DIRECTORY_SEPARATOR . $file)) === FALSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
self::removeBlankDir($target);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -447,37 +281,7 @@ class FileHandler
|
|||
*/
|
||||
public static function removeFilesInDir($path)
|
||||
{
|
||||
if(($path = self::getRealPath($path)) === FALSE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(is_dir($path))
|
||||
{
|
||||
$files = array_diff(scandir($path), array('..', '.'));
|
||||
|
||||
foreach($files as $file)
|
||||
{
|
||||
if(($target = self::getRealPath($path . DIRECTORY_SEPARATOR . $file)) === FALSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(is_dir($target))
|
||||
{
|
||||
self::removeFilesInDir($target);
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink($target);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(self::exists($path)) unlink($path);
|
||||
}
|
||||
|
||||
return Rhymix\Framework\Storage::deleteDirectory(self::getRealPath($path), false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -584,7 +388,14 @@ class FileHandler
|
|||
|
||||
if($response->success)
|
||||
{
|
||||
return $response->body;
|
||||
if (isset($request_config['filename']))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $response->body;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -611,13 +422,9 @@ class FileHandler
|
|||
*/
|
||||
public static function getRemoteFile($url, $target_filename, $body = null, $timeout = 3, $method = 'GET', $content_type = null, $headers = array(), $cookies = array(), $post_data = array(), $request_config = array())
|
||||
{
|
||||
if(!($body = self::getRemoteResource($url, $body, $timeout, $method, $content_type, $headers,$cookies,$post_data,$request_config)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self::writeFile($target_filename, $body);
|
||||
return TRUE;
|
||||
$request_config['filename'] = $target_filename;
|
||||
$success = self::getRemoteResource($url, $body, $timeout, $method, $content_type, $headers, $cookies, $post_data, $request_config);
|
||||
return $success ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -658,12 +465,17 @@ class FileHandler
|
|||
$channels = 6; //for png
|
||||
}
|
||||
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $channels / 8 + $K64 ) * $TWEAKFACTOR);
|
||||
$availableMemory = self::returnBytes(ini_get('memory_limit')) - memory_get_usage();
|
||||
$memoryLimit = self::returnBytes(ini_get('memory_limit'));
|
||||
if($memoryLimit < 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
$availableMemory = $memoryLimit - memory_get_usage();
|
||||
if($availableMemory < $memoryNeeded)
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
return TRUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -882,19 +694,13 @@ class FileHandler
|
|||
*/
|
||||
public static function readIniFile($filename)
|
||||
{
|
||||
if(($filename = self::exists($filename)) === FALSE)
|
||||
if(!Rhymix\Framework\Storage::isReadable($filename))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
$arr = parse_ini_file($filename, TRUE);
|
||||
if(is_array($arr) && count($arr) > 0)
|
||||
{
|
||||
return $arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return array();
|
||||
return false;
|
||||
}
|
||||
|
||||
$arr = parse_ini_file($filename, true);
|
||||
return is_array($arr) ? $arr : array();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -966,11 +772,9 @@ class FileHandler
|
|||
*/
|
||||
public static function openFile($filename, $mode)
|
||||
{
|
||||
$pathinfo = pathinfo($filename);
|
||||
self::makeDir($pathinfo['dirname']);
|
||||
|
||||
require_once("FileObject.class.php");
|
||||
return new FileObject($filename, $mode);
|
||||
$filename = self::getRealPath($filename);
|
||||
Rhymix\Framework\Storage::createDirectory(dirname($filename));
|
||||
return new FileObject($filename, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -981,7 +785,7 @@ class FileHandler
|
|||
*/
|
||||
public static function hasContent($filename)
|
||||
{
|
||||
return (is_readable($filename) && (filesize($filename) > 0));
|
||||
return Rhymix\Framework\Storage::getSize(self::getRealPath($filename)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -993,7 +797,7 @@ class FileHandler
|
|||
public static function exists($filename)
|
||||
{
|
||||
$filename = self::getRealPath($filename);
|
||||
return file_exists($filename) ? $filename : FALSE;
|
||||
return Rhymix\Framework\Storage::exists($filename) ? $filename : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1005,7 +809,7 @@ class FileHandler
|
|||
public static function isDir($path)
|
||||
{
|
||||
$path = self::getRealPath($path);
|
||||
return is_dir($path) ? $path : FALSE;
|
||||
return Rhymix\Framework\Storage::isDirectory($path) ? $path : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1017,22 +821,7 @@ class FileHandler
|
|||
public static function isWritableDir($path)
|
||||
{
|
||||
$path = self::getRealPath($path);
|
||||
if(is_dir($path)==FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$checkFile = $path . '/_CheckWritableDir';
|
||||
|
||||
$fp = fopen($checkFile, 'w');
|
||||
if(!is_resource($fp))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
fclose($fp);
|
||||
|
||||
self::removeFile($checkFile);
|
||||
return TRUE;
|
||||
return Rhymix\Framework\Storage::isDirectory($path) && Rhymix\Framework\Storage::isWritable($path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -460,81 +460,7 @@ class Mail
|
|||
*/
|
||||
function returnMIMEType($filename)
|
||||
{
|
||||
preg_match("|\.([a-z0-9]{2,4})$|i", $filename, $fileSuffix);
|
||||
switch(strtolower($fileSuffix[1]))
|
||||
{
|
||||
case "js" :
|
||||
return "application/x-javascript";
|
||||
case "json" :
|
||||
return "application/json";
|
||||
case "jpg" :
|
||||
case "jpeg" :
|
||||
case "jpe" :
|
||||
return "image/jpg";
|
||||
case "png" :
|
||||
case "gif" :
|
||||
case "bmp" :
|
||||
case "tiff" :
|
||||
return "image/" . strtolower($fileSuffix[1]);
|
||||
case "css" :
|
||||
return "text/css";
|
||||
case "xml" :
|
||||
return "application/xml";
|
||||
case "doc" :
|
||||
case "docx" :
|
||||
return "application/msword";
|
||||
case "xls" :
|
||||
case "xlt" :
|
||||
case "xlm" :
|
||||
case "xld" :
|
||||
case "xla" :
|
||||
case "xlc" :
|
||||
case "xlw" :
|
||||
case "xll" :
|
||||
return "application/vnd.ms-excel";
|
||||
case "ppt" :
|
||||
case "pps" :
|
||||
return "application/vnd.ms-powerpoint";
|
||||
case "rtf" :
|
||||
return "application/rtf";
|
||||
case "pdf" :
|
||||
return "application/pdf";
|
||||
case "html" :
|
||||
case "htm" :
|
||||
case "php" :
|
||||
return "text/html";
|
||||
case "txt" :
|
||||
return "text/plain";
|
||||
case "mpeg" :
|
||||
case "mpg" :
|
||||
case "mpe" :
|
||||
return "video/mpeg";
|
||||
case "mp3" :
|
||||
return "audio/mpeg3";
|
||||
case "wav" :
|
||||
return "audio/wav";
|
||||
case "aiff" :
|
||||
case "aif" :
|
||||
return "audio/aiff";
|
||||
case "avi" :
|
||||
return "video/msvideo";
|
||||
case "wmv" :
|
||||
return "video/x-ms-wmv";
|
||||
case "mov" :
|
||||
return "video/quicktime";
|
||||
case "zip" :
|
||||
return "application/zip";
|
||||
case "tar" :
|
||||
return "application/x-tar";
|
||||
case "swf" :
|
||||
return "application/x-shockwave-flash";
|
||||
default :
|
||||
if(function_exists("mime_content_type"))
|
||||
{
|
||||
$fileSuffix = mime_content_type($filename);
|
||||
}
|
||||
return "unknown/" . trim($fileSuffix[0], ".");
|
||||
}
|
||||
return Rhymix\Framework\MIME::getTypeByFilename($filename);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,9 +55,6 @@ class Mobile
|
|||
return $this->ismobile = false;
|
||||
}
|
||||
|
||||
$xe_web_path = Context::pathToUrl(_XE_PATH_);
|
||||
|
||||
// default setting. if there is cookie for a device, XE do not have to check if it is mobile or not and it will enhance performace of the server.
|
||||
$this->ismobile = FALSE;
|
||||
|
||||
$m = Context::get('m');
|
||||
|
|
@ -87,28 +84,14 @@ class Mobile
|
|||
}
|
||||
else
|
||||
{
|
||||
$this->ismobile = FALSE;
|
||||
setcookie("mobile", FALSE, 0, $xe_web_path);
|
||||
setcookie("user-agent", FALSE, 0, $xe_web_path);
|
||||
if(!self::isMobilePadCheckByAgent() && self::isMobileCheckByAgent())
|
||||
{
|
||||
$this->ismobile = TRUE;
|
||||
}
|
||||
setcookie("mobile", FALSE, 0, RX_BASEURL);
|
||||
setcookie("user-agent", FALSE, 0, RX_BASEURL);
|
||||
$this->ismobile = Rhymix\Framework\UA::isMobile() && !Rhymix\Framework\UA::isTablet();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(self::isMobilePadCheckByAgent())
|
||||
{
|
||||
$this->ismobile = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(self::isMobileCheckByAgent())
|
||||
{
|
||||
$this->ismobile = TRUE;
|
||||
}
|
||||
}
|
||||
$this->ismobile = Rhymix\Framework\UA::isMobile() && !Rhymix\Framework\UA::isTablet();
|
||||
}
|
||||
|
||||
if($this->ismobile !== NULL)
|
||||
|
|
@ -118,18 +101,18 @@ class Mobile
|
|||
if($_COOKIE['mobile'] != 'true')
|
||||
{
|
||||
$_COOKIE['mobile'] = 'true';
|
||||
setcookie("mobile", 'true', 0, $xe_web_path);
|
||||
setcookie("mobile", 'true', 0, RX_BASEURL);
|
||||
}
|
||||
}
|
||||
elseif(isset($_COOKIE['mobile']) && $_COOKIE['mobile'] != 'false')
|
||||
{
|
||||
$_COOKIE['mobile'] = 'false';
|
||||
setcookie("mobile", 'false', 0, $xe_web_path);
|
||||
setcookie("mobile", 'false', 0, RX_BASEURL);
|
||||
}
|
||||
|
||||
if(isset($_COOKIE['mobile']) && $_COOKIE['user-agent'] != md5($_SERVER['HTTP_USER_AGENT']))
|
||||
{
|
||||
setcookie("user-agent", md5($_SERVER['HTTP_USER_AGENT']), 0, $xe_web_path);
|
||||
setcookie("user-agent", md5($_SERVER['HTTP_USER_AGENT']), 0, RX_BASEURL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,31 +126,7 @@ class Mobile
|
|||
*/
|
||||
public static function isMobileCheckByAgent()
|
||||
{
|
||||
static $UACheck;
|
||||
if(isset($UACheck))
|
||||
{
|
||||
return $UACheck;
|
||||
}
|
||||
|
||||
$oMobile = Mobile::getInstance();
|
||||
$mobileAgent = array('iPod', 'iPhone', 'Android', 'BlackBerry', 'SymbianOS', 'Bada', 'Tizen', 'Kindle', 'Wii', 'SCH-', 'SPH-', 'CANU-', 'Windows Phone', 'Windows CE', 'POLARIS', 'Palm', 'Dorothy Browser', 'Mobile', 'Opera Mobi', 'Opera Mini', 'Minimo', 'AvantGo', 'NetFront', 'Nokia', 'LGPlayer', 'SonyEricsson', 'HTC');
|
||||
|
||||
if($oMobile->isMobilePadCheckByAgent())
|
||||
{
|
||||
$UACheck = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
foreach($mobileAgent as $agent)
|
||||
{
|
||||
if(stripos($_SERVER['HTTP_USER_AGENT'], $agent) !== FALSE)
|
||||
{
|
||||
$UACheck = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
$UACheck = FALSE;
|
||||
return FALSE;
|
||||
return Rhymix\Framework\UA::isMobile();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -177,45 +136,7 @@ class Mobile
|
|||
*/
|
||||
public static function isMobilePadCheckByAgent()
|
||||
{
|
||||
static $UACheck;
|
||||
if(isset($UACheck))
|
||||
{
|
||||
return $UACheck;
|
||||
}
|
||||
$padAgent = array('iPad', 'Android', 'webOS', 'hp-tablet', 'PlayBook');
|
||||
|
||||
// Android with 'Mobile' string is not a tablet-like device, and 'Andoroid' without 'Mobile' string is a tablet-like device.
|
||||
// $exceptionAgent[0] contains exception agents for all exceptions.
|
||||
$exceptionAgent = array(0 => array('Opera Mini', 'Opera Mobi'), 'Android' => 'Mobile');
|
||||
|
||||
foreach($padAgent as $agent)
|
||||
{
|
||||
if(strpos($_SERVER['HTTP_USER_AGENT'], $agent) !== FALSE)
|
||||
{
|
||||
if(!isset($exceptionAgent[$agent]))
|
||||
{
|
||||
$UACheck = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
elseif(strpos($_SERVER['HTTP_USER_AGENT'], $exceptionAgent[$agent]) === FALSE)
|
||||
{
|
||||
// If the agent is the Android, that can be either tablet and mobile phone.
|
||||
foreach($exceptionAgent[0] as $val)
|
||||
{
|
||||
if(strpos($_SERVER['HTTP_USER_AGENT'], $val) !== FALSE)
|
||||
{
|
||||
$UACheck = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
$UACheck = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$UACheck = FALSE;
|
||||
return FALSE;
|
||||
return Rhymix\Framework\UA::isTablet();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ class ModuleHandler extends Handler
|
|||
}
|
||||
|
||||
// redirect, if site_srl of module_info is different from one of site's module_info
|
||||
if($module_info && $module_info->site_srl != $site_module_info->site_srl && !isCrawler())
|
||||
if($module_info && $module_info->site_srl != $site_module_info->site_srl && !Rhymix\Framework\UA::isRobot())
|
||||
{
|
||||
// If the module is of virtual site
|
||||
if($module_info->site_srl)
|
||||
|
|
@ -1289,6 +1289,8 @@ class ModuleHandler extends Handler
|
|||
$statusMessageList = array(
|
||||
'100' => 'Continue',
|
||||
'101' => 'Switching Protocols',
|
||||
'102' => 'Processing',
|
||||
'103' => 'Checkpoint',
|
||||
'200' => 'OK',
|
||||
'201' => 'Created',
|
||||
'202' => 'Accepted',
|
||||
|
|
@ -1296,13 +1298,18 @@ class ModuleHandler extends Handler
|
|||
'204' => 'No Content',
|
||||
'205' => 'Reset Content',
|
||||
'206' => 'Partial Content',
|
||||
'207' => 'Multi-Status',
|
||||
'208' => 'Already Reported',
|
||||
'226' => 'IM Used',
|
||||
'300' => 'Multiple Choices',
|
||||
'301' => 'Moved Permanently',
|
||||
'302' => 'Found',
|
||||
'303' => 'See Other',
|
||||
'304' => 'Not Modified',
|
||||
'305' => 'Use Proxy',
|
||||
'306' => 'Switch Proxy',
|
||||
'307' => 'Temporary Redirect',
|
||||
'308' => 'Permanent Redirect',
|
||||
'400' => 'Bad Request',
|
||||
'401' => 'Unauthorized',
|
||||
'402' => 'Payment Required',
|
||||
|
|
@ -1316,19 +1323,39 @@ class ModuleHandler extends Handler
|
|||
'410' => 'Gone',
|
||||
'411' => 'Length Required',
|
||||
'412' => 'Precondition Failed',
|
||||
'413' => 'Request Entity Too Large',
|
||||
'414' => 'Request-URI Too Long',
|
||||
'413' => 'Payload Too Large',
|
||||
'414' => 'URI Too Long',
|
||||
'415' => 'Unsupported Media Type',
|
||||
'416' => 'Requested Range Not Satisfiable',
|
||||
'416' => 'Range Not Satisfiable',
|
||||
'417' => 'Expectation Failed',
|
||||
'418' => 'I\'m a teapot',
|
||||
'420' => 'Enhance Your Calm',
|
||||
'421' => 'Misdirected Request',
|
||||
'422' => 'Unprocessable Entity',
|
||||
'423' => 'Locked',
|
||||
'424' => 'Failed Dependency',
|
||||
'425' => 'Unordered Collection',
|
||||
'426' => 'Upgrade Required',
|
||||
'428' => 'Precondition Required',
|
||||
'429' => 'Too Many Requests',
|
||||
'431' => 'Request Header Fields Too Large',
|
||||
'444' => 'No Response',
|
||||
'449' => 'Retry With',
|
||||
'451' => 'Unavailable For Legal Reasons',
|
||||
'500' => 'Internal Server Error',
|
||||
'501' => 'Not Implemented',
|
||||
'502' => 'Bad Gateway',
|
||||
'503' => 'Service Unavailable',
|
||||
'504' => 'Gateway Timeout',
|
||||
'505' => 'HTTP Version Not Supported',
|
||||
'506' => 'Variant Also Negotiates',
|
||||
'507' => 'Insufficient Storage',
|
||||
'508' => 'Loop Detected',
|
||||
'509' => 'Bandwidth Limit Exceeded',
|
||||
'510' => 'Not Extended',
|
||||
'511' => 'Network Authentication Required',
|
||||
);
|
||||
$statusMessage = $statusMessageList[$code];
|
||||
$statusMessage = $statusMessageList[strval($code)];
|
||||
if(!$statusMessage)
|
||||
{
|
||||
$statusMessage = 'OK';
|
||||
|
|
|
|||
2259
common/defaults/countries.php
Normal file
2259
common/defaults/countries.php
Normal file
File diff suppressed because it is too large
Load diff
3863
common/defaults/korea.ipv4.php
Normal file
3863
common/defaults/korea.ipv4.php
Normal file
File diff suppressed because it is too large
Load diff
503
common/defaults/korea.ipv6.php
Normal file
503
common/defaults/korea.ipv6.php
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Source: https://ip.kisa.or.kr/ip_cate_stat/stat_05_05.act
|
||||
* Last Updated: 2016-03-18
|
||||
*/
|
||||
return array (
|
||||
0 =>
|
||||
array (
|
||||
0 => '2001000000000000',
|
||||
1 => '2001000fffffffff',
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
0 => '2001022000000000',
|
||||
1 => '20010220ffffffff',
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
0 => '2001023000000000',
|
||||
1 => '20010230ffffffff',
|
||||
),
|
||||
3 =>
|
||||
array (
|
||||
0 => '2001027000000000',
|
||||
1 => '20010270ffffffff',
|
||||
),
|
||||
4 =>
|
||||
array (
|
||||
0 => '2001028000000000',
|
||||
1 => '20010280ffffffff',
|
||||
),
|
||||
5 =>
|
||||
array (
|
||||
0 => '2001029000000000',
|
||||
1 => '20010290ffffffff',
|
||||
),
|
||||
6 =>
|
||||
array (
|
||||
0 => '200102b000000000',
|
||||
1 => '200102b0ffffffff',
|
||||
),
|
||||
7 =>
|
||||
array (
|
||||
0 => '200102b800000000',
|
||||
1 => '200102b8ffffffff',
|
||||
),
|
||||
8 =>
|
||||
array (
|
||||
0 => '200102d800000000',
|
||||
1 => '200102d8ffffffff',
|
||||
),
|
||||
9 =>
|
||||
array (
|
||||
0 => '2001032000000000',
|
||||
1 => '20010320ffffffff',
|
||||
),
|
||||
10 =>
|
||||
array (
|
||||
0 => '2001033000000000',
|
||||
1 => '20010330ffffffff',
|
||||
),
|
||||
11 =>
|
||||
array (
|
||||
0 => '2001037800000000',
|
||||
1 => '20010378ffffffff',
|
||||
),
|
||||
12 =>
|
||||
array (
|
||||
0 => '2001039000000000',
|
||||
1 => '20010390ffffffff',
|
||||
),
|
||||
13 =>
|
||||
array (
|
||||
0 => '200103a800000000',
|
||||
1 => '200103a8ffffffff',
|
||||
),
|
||||
14 =>
|
||||
array (
|
||||
0 => '200107fa00000002',
|
||||
1 => '200107fa00000002',
|
||||
),
|
||||
15 =>
|
||||
array (
|
||||
0 => '200107fa00080000',
|
||||
1 => '200107fa0008ffff',
|
||||
),
|
||||
16 =>
|
||||
array (
|
||||
0 => '20010c4800000000',
|
||||
1 => '20010c48ffffffff',
|
||||
),
|
||||
17 =>
|
||||
array (
|
||||
0 => '20010c9800000000',
|
||||
1 => '20010c98ffffffff',
|
||||
),
|
||||
18 =>
|
||||
array (
|
||||
0 => '20010cf000000000',
|
||||
1 => '20010cf0ffffffff',
|
||||
),
|
||||
19 =>
|
||||
array (
|
||||
0 => '20010d3800000000',
|
||||
1 => '20010d38ffffffff',
|
||||
),
|
||||
20 =>
|
||||
array (
|
||||
0 => '20010dc500000000',
|
||||
1 => '20010dc5ffffffff',
|
||||
),
|
||||
21 =>
|
||||
array (
|
||||
0 => '20010dcc00000000',
|
||||
1 => '20010dccffffffff',
|
||||
),
|
||||
22 =>
|
||||
array (
|
||||
0 => '20010ea000000000',
|
||||
1 => '20010ea0ffffffff',
|
||||
),
|
||||
23 =>
|
||||
array (
|
||||
0 => '20010ea800000000',
|
||||
1 => '20010ea8ffffffff',
|
||||
),
|
||||
24 =>
|
||||
array (
|
||||
0 => '20010eb800000000',
|
||||
1 => '20010eb8ffffffff',
|
||||
),
|
||||
25 =>
|
||||
array (
|
||||
0 => '20010ed000000000',
|
||||
1 => '20010ed0ffffffff',
|
||||
),
|
||||
26 =>
|
||||
array (
|
||||
0 => '20010ee800000000',
|
||||
1 => '20010ee8ffffffff',
|
||||
),
|
||||
27 =>
|
||||
array (
|
||||
0 => '20010ef000000000',
|
||||
1 => '20010ef0ffffffff',
|
||||
),
|
||||
28 =>
|
||||
array (
|
||||
0 => '20010ef800000000',
|
||||
1 => '20010ef8ffffffff',
|
||||
),
|
||||
29 =>
|
||||
array (
|
||||
0 => '20010f2800000000',
|
||||
1 => '20010f28ffffffff',
|
||||
),
|
||||
30 =>
|
||||
array (
|
||||
0 => '20010f4800000000',
|
||||
1 => '20010f48ffffffff',
|
||||
),
|
||||
31 =>
|
||||
array (
|
||||
0 => '24033e0000000000',
|
||||
1 => '24033e00ffffffff',
|
||||
),
|
||||
32 =>
|
||||
array (
|
||||
0 => '2001443000000000',
|
||||
1 => '20014430ffffffff',
|
||||
),
|
||||
33 =>
|
||||
array (
|
||||
0 => '2400000000000000',
|
||||
1 => '24000fffffffffff',
|
||||
),
|
||||
34 =>
|
||||
array (
|
||||
0 => '2400180000000000',
|
||||
1 => '24001800ffffffff',
|
||||
),
|
||||
35 =>
|
||||
array (
|
||||
0 => '2400330000000000',
|
||||
1 => '24003300ffffffff',
|
||||
),
|
||||
36 =>
|
||||
array (
|
||||
0 => '2400478000000000',
|
||||
1 => '24004780ffffffff',
|
||||
),
|
||||
37 =>
|
||||
array (
|
||||
0 => '2400498000000000',
|
||||
1 => '24004980ffffffff',
|
||||
),
|
||||
38 =>
|
||||
array (
|
||||
0 => '24009f8000000000',
|
||||
1 => '24009f80ffffffff',
|
||||
),
|
||||
39 =>
|
||||
array (
|
||||
0 => '2400a58000000000',
|
||||
1 => '2400a580ffffffff',
|
||||
),
|
||||
40 =>
|
||||
array (
|
||||
0 => '2400ab0000000000',
|
||||
1 => '2400ab00ffffffff',
|
||||
),
|
||||
41 =>
|
||||
array (
|
||||
0 => '2400cf0000000000',
|
||||
1 => '2400cf00ffffffff',
|
||||
),
|
||||
42 =>
|
||||
array (
|
||||
0 => '2400fd8000000000',
|
||||
1 => '2400fd80ffffffff',
|
||||
),
|
||||
43 =>
|
||||
array (
|
||||
0 => '2401270000000000',
|
||||
1 => '24012700ffffffff',
|
||||
),
|
||||
44 =>
|
||||
array (
|
||||
0 => '2401400000000000',
|
||||
1 => '24014000ffffffff',
|
||||
),
|
||||
45 =>
|
||||
array (
|
||||
0 => '2401a00000000000',
|
||||
1 => '2401a000ffffffff',
|
||||
),
|
||||
46 =>
|
||||
array (
|
||||
0 => '2401a80000000000',
|
||||
1 => '2401a800ffffffff',
|
||||
),
|
||||
47 =>
|
||||
array (
|
||||
0 => '2401c50000000000',
|
||||
1 => '2401c500ffffffff',
|
||||
),
|
||||
48 =>
|
||||
array (
|
||||
0 => '2402000000000000',
|
||||
1 => '240200ffffffffff',
|
||||
),
|
||||
49 =>
|
||||
array (
|
||||
0 => '24021a0000000000',
|
||||
1 => '24021a00ffffffff',
|
||||
),
|
||||
50 =>
|
||||
array (
|
||||
0 => '2402310000000000',
|
||||
1 => '24023100ffffffff',
|
||||
),
|
||||
51 =>
|
||||
array (
|
||||
0 => '2402580000000000',
|
||||
1 => '24025800ffffffff',
|
||||
),
|
||||
52 =>
|
||||
array (
|
||||
0 => '2402610000000000',
|
||||
1 => '24026100ffffffff',
|
||||
),
|
||||
53 =>
|
||||
array (
|
||||
0 => '2402700000000000',
|
||||
1 => '24027000ffffffff',
|
||||
),
|
||||
54 =>
|
||||
array (
|
||||
0 => '2402be0000000000',
|
||||
1 => '2402be00ffffffff',
|
||||
),
|
||||
55 =>
|
||||
array (
|
||||
0 => '2402de0000000000',
|
||||
1 => '2402de00ffffffff',
|
||||
),
|
||||
56 =>
|
||||
array (
|
||||
0 => '2402f40000000000',
|
||||
1 => '2402f400ffffffff',
|
||||
),
|
||||
57 =>
|
||||
array (
|
||||
0 => '2403370000000000',
|
||||
1 => '24033700ffffffff',
|
||||
),
|
||||
58 =>
|
||||
array (
|
||||
0 => '2403630000000000',
|
||||
1 => '24036300ffffffff',
|
||||
),
|
||||
59 =>
|
||||
array (
|
||||
0 => '2403650000000000',
|
||||
1 => '24036500ffffffff',
|
||||
),
|
||||
60 =>
|
||||
array (
|
||||
0 => '2404000000000000',
|
||||
1 => '2404000fffffffff',
|
||||
),
|
||||
61 =>
|
||||
array (
|
||||
0 => '2404080000000000',
|
||||
1 => '24040800ffffffff',
|
||||
),
|
||||
62 =>
|
||||
array (
|
||||
0 => '2404230000000000',
|
||||
1 => '24042300ffffffff',
|
||||
),
|
||||
63 =>
|
||||
array (
|
||||
0 => '2404460000000000',
|
||||
1 => '24044600ffffffff',
|
||||
),
|
||||
64 =>
|
||||
array (
|
||||
0 => '2405350000000000',
|
||||
1 => '24053500ffffffff',
|
||||
),
|
||||
65 =>
|
||||
array (
|
||||
0 => '2405430000000000',
|
||||
1 => '24054300ffffffff',
|
||||
),
|
||||
66 =>
|
||||
array (
|
||||
0 => '2405580000000000',
|
||||
1 => '24055800ffffffff',
|
||||
),
|
||||
67 =>
|
||||
array (
|
||||
0 => '20010e6000000000',
|
||||
1 => '20010e60ffffffff',
|
||||
),
|
||||
68 =>
|
||||
array (
|
||||
0 => '20010e7000000000',
|
||||
1 => '20010e70ffffffff',
|
||||
),
|
||||
69 =>
|
||||
array (
|
||||
0 => '20010e7800000000',
|
||||
1 => '20010e78ffffffff',
|
||||
),
|
||||
70 =>
|
||||
array (
|
||||
0 => '20010e9800000000',
|
||||
1 => '20010e98ffffffff',
|
||||
),
|
||||
71 =>
|
||||
array (
|
||||
0 => '24009e8000000000',
|
||||
1 => '24009e80ffffffff',
|
||||
),
|
||||
72 =>
|
||||
array (
|
||||
0 => '2400e18000000000',
|
||||
1 => '2400e180ffffffff',
|
||||
),
|
||||
73 =>
|
||||
array (
|
||||
0 => '2401e20000000000',
|
||||
1 => '2401e200ffffffff',
|
||||
),
|
||||
74 =>
|
||||
array (
|
||||
0 => '24053d0000000000',
|
||||
1 => '24053d00ffffffff',
|
||||
),
|
||||
75 =>
|
||||
array (
|
||||
0 => '24055f0000000000',
|
||||
1 => '24055f00ffffffff',
|
||||
),
|
||||
76 =>
|
||||
array (
|
||||
0 => '24057b0000000000',
|
||||
1 => '24057b00ffffffff',
|
||||
),
|
||||
77 =>
|
||||
array (
|
||||
0 => '2405860000000000',
|
||||
1 => '24058600ffffffff',
|
||||
),
|
||||
78 =>
|
||||
array (
|
||||
0 => '2405950000000000',
|
||||
1 => '24059500ffffffff',
|
||||
),
|
||||
79 =>
|
||||
array (
|
||||
0 => '2405c00000000000',
|
||||
1 => '2405c000ffffffff',
|
||||
),
|
||||
80 =>
|
||||
array (
|
||||
0 => '2406400000000000',
|
||||
1 => '24064000ffffffff',
|
||||
),
|
||||
81 =>
|
||||
array (
|
||||
0 => '2406590000000000',
|
||||
1 => '24065900ffffffff',
|
||||
),
|
||||
82 =>
|
||||
array (
|
||||
0 => '2406660000000000',
|
||||
1 => '24066600ffffffff',
|
||||
),
|
||||
83 =>
|
||||
array (
|
||||
0 => '2406680000000000',
|
||||
1 => '24066800ffffffff',
|
||||
),
|
||||
84 =>
|
||||
array (
|
||||
0 => '24066a0000000000',
|
||||
1 => '24066a00ffffffff',
|
||||
),
|
||||
85 =>
|
||||
array (
|
||||
0 => '2406ad0000000000',
|
||||
1 => '2406ad00ffffffff',
|
||||
),
|
||||
86 =>
|
||||
array (
|
||||
0 => '2406b00000000000',
|
||||
1 => '2406b000ffffffff',
|
||||
),
|
||||
87 =>
|
||||
array (
|
||||
0 => '2406d00000000000',
|
||||
1 => '2406d000ffffffff',
|
||||
),
|
||||
88 =>
|
||||
array (
|
||||
0 => '2406d70000000000',
|
||||
1 => '2406d700ffffffff',
|
||||
),
|
||||
89 =>
|
||||
array (
|
||||
0 => '24070b0000000000',
|
||||
1 => '24070b00ffffffff',
|
||||
),
|
||||
90 =>
|
||||
array (
|
||||
0 => '2407200000000000',
|
||||
1 => '24072000ffffffff',
|
||||
),
|
||||
91 =>
|
||||
array (
|
||||
0 => '2407350000000000',
|
||||
1 => '24073500ffffffff',
|
||||
),
|
||||
92 =>
|
||||
array (
|
||||
0 => '2407650000000000',
|
||||
1 => '24076500ffffffff',
|
||||
),
|
||||
93 =>
|
||||
array (
|
||||
0 => '2407670000000000',
|
||||
1 => '24076700ffffffff',
|
||||
),
|
||||
94 =>
|
||||
array (
|
||||
0 => '2407910000000000',
|
||||
1 => '24079100ffffffff',
|
||||
),
|
||||
95 =>
|
||||
array (
|
||||
0 => '2407b20000000000',
|
||||
1 => '2407b200ffffffff',
|
||||
),
|
||||
96 =>
|
||||
array (
|
||||
0 => '2407b80000000000',
|
||||
1 => '2407b800ffffffff',
|
||||
),
|
||||
97 =>
|
||||
array (
|
||||
0 => '2407c00000000000',
|
||||
1 => '2407c000ffffffff',
|
||||
),
|
||||
98 =>
|
||||
array (
|
||||
0 => '2407c70000000000',
|
||||
1 => '2407c700ffffffff',
|
||||
),
|
||||
);
|
||||
132
common/framework/calendar.php
Normal file
132
common/framework/calendar.php
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* The calendar class.
|
||||
*/
|
||||
class Calendar
|
||||
{
|
||||
/**
|
||||
* This method returns the English name of a month, e.g. 9 = 'September'.
|
||||
*
|
||||
* @param int $month_number
|
||||
* @param bool $long_format (optional, default is true)
|
||||
* @return string
|
||||
*/
|
||||
public static function getMonthName($month_number, $long_format = true)
|
||||
{
|
||||
$month_number = intval($month_number, 10);
|
||||
if (!is_between($month_number, 1, 12))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return date($long_format ? 'F' : 'M', mktime(0, 0, 0, $month_number, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the day on which a month begins.
|
||||
*
|
||||
* 0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 = Thursday, 5 = Friday, 6 = Saturday.
|
||||
* If you do not specify a year, the current year is assumed.
|
||||
*
|
||||
* @param int $month_number
|
||||
* @param int $year (optional)
|
||||
* @return int
|
||||
*/
|
||||
public static function getMonthStartDayOfWeek($month_number, $year = null)
|
||||
{
|
||||
$month_number = intval($month_number, 10);
|
||||
if (!is_between($month_number, 1, 12))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int)date('w', mktime(0, 0, 0, $month_number, 1, $year ?: date('Y')));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the number of days in a month, e.g. February 2016 has 29 days.
|
||||
*
|
||||
* If you do not specify a year, the current year is assumed.
|
||||
* You must specify a year to get the number of days in February.
|
||||
*
|
||||
* @param int $month_number
|
||||
* @param int $year (optional)
|
||||
* @return int
|
||||
*/
|
||||
public static function getMonthDays($month_number, $year = null)
|
||||
{
|
||||
$month_number = intval($month_number, 10);
|
||||
if (!is_between($month_number, 1, 12))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int)date('t', mktime(0, 0, 0, $month_number, 1, $year ?: date('Y')));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a complete calendar for a month.
|
||||
*
|
||||
* The return value is an array with six members, each representing a week.
|
||||
* Each week is an array with seven members, each representing a day.
|
||||
* 6 weeks are returned. Empty cells are represented by nulls.
|
||||
*
|
||||
* If you do not specify a year, the current year is assumed.
|
||||
*
|
||||
* @param int $month_number
|
||||
* @param int $year (optional)
|
||||
* @param int $start_dow (optional)
|
||||
* @return array
|
||||
*/
|
||||
public static function getMonthCalendar($month_number, $year = null, $start_dow = 0)
|
||||
{
|
||||
$month_number = intval($month_number, 10);
|
||||
if (!is_between($month_number, 1, 12))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!is_between($start_dow, 0, 6))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!$year || !is_between($year, 1000, 9999))
|
||||
{
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$start = self::getMonthStartDayOfWeek($month_number, $year);
|
||||
$count = self::getMonthDays($month_number, $year);
|
||||
$initial_blank_cells = (7 + $start - $start_dow) % 7;
|
||||
$final_blank_cells = 42 - $count - $initial_blank_cells;
|
||||
$temp = array();
|
||||
|
||||
for ($i = 0; $i < $initial_blank_cells; $i++)
|
||||
{
|
||||
$temp[] = null;
|
||||
}
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
$temp[] = $i + 1;
|
||||
}
|
||||
for ($i = 0; $i < $final_blank_cells; $i++)
|
||||
{
|
||||
$temp[] = null;
|
||||
}
|
||||
|
||||
$return = array();
|
||||
for ($i = 0; $i < 6; $i++)
|
||||
{
|
||||
$week = array();
|
||||
for ($j = 0; $j < 7; $j++)
|
||||
{
|
||||
$week[] = array_shift($temp);
|
||||
}
|
||||
$return[] = $week;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,9 +28,9 @@ class Config
|
|||
*/
|
||||
public static function init()
|
||||
{
|
||||
if (file_exists(RX_BASEDIR . self::$config_filename))
|
||||
if (file_exists(\RX_BASEDIR . self::$config_filename))
|
||||
{
|
||||
self::$_config = (include RX_BASEDIR . self::$config_filename);
|
||||
self::$_config = (include \RX_BASEDIR . self::$config_filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -59,7 +59,7 @@ class Config
|
|||
*/
|
||||
public static function getDefaults()
|
||||
{
|
||||
return (include RX_BASEDIR . self::$default_config_filename);
|
||||
return (include \RX_BASEDIR . self::$default_config_filename);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -135,7 +135,7 @@ class Config
|
|||
|
||||
// Save the main config file.
|
||||
$buff = '<?php' . "\n" . '// Rhymix System Configuration' . "\n" . 'return ' . self::serialize(self::$_config) . ';' . "\n";
|
||||
$result = \FileHandler::writeFile(RX_BASEDIR . self::$config_filename, $buff) ? true : false;
|
||||
$result = Storage::write(\RX_BASEDIR . self::$config_filename, $buff) ? true : false;
|
||||
//if (!$result) return false;
|
||||
|
||||
// Save XE-compatible config files.
|
||||
|
|
@ -144,9 +144,9 @@ class Config
|
|||
$db_info_without_ftp = clone $db_info;
|
||||
unset($db_info_without_ftp->ftp_info);
|
||||
$buff = '<?php' . "\n" . '$db_info = ' . self::serialize($db_info_without_ftp) . ';' . "\n";
|
||||
\FileHandler::writeFile(RX_BASEDIR . self::$old_db_config_filename, $buff);
|
||||
Storage::write(\RX_BASEDIR . self::$old_db_config_filename, $buff);
|
||||
$buff = '<?php' . "\n" . '$ftp_info = ' . self::serialize($ftp_info) . ';' . "\n";
|
||||
\FileHandler::writeFile(RX_BASEDIR . self::$old_ftp_config_filename, $buff);
|
||||
Storage::write(\RX_BASEDIR . self::$old_ftp_config_filename, $buff);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -173,8 +173,8 @@ class Debug
|
|||
|
||||
// Rewrite the error message with relative paths.
|
||||
$message = str_replace(array(
|
||||
' called in ' . RX_BASEDIR,
|
||||
' defined in ' . RX_BASEDIR,
|
||||
' called in ' . \RX_BASEDIR,
|
||||
' defined in ' . \RX_BASEDIR,
|
||||
), array(
|
||||
' called in ',
|
||||
' defined in ',
|
||||
|
|
@ -485,7 +485,7 @@ class Debug
|
|||
{
|
||||
// Collect debug information.
|
||||
$data = (object)array(
|
||||
'timestamp' => DateTime::formatTimestamp('Y-m-d H:i:s', RX_TIME),
|
||||
'timestamp' => DateTime::formatTimestamp('Y-m-d H:i:s', \RX_TIME),
|
||||
'url' => getCurrentPageUrl(),
|
||||
'request' => (object)array(
|
||||
'method' => $_SERVER['REQUEST_METHOD'] . ($_SERVER['REQUEST_METHOD'] !== \Context::getRequestMethod() ? (' (' . \Context::getRequestMethod() . ')') : ''),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Rhymix\Framework\Filters;
|
||||
|
||||
use Rhymix\Framework\Security;
|
||||
use Rhymix\Framework\Storage;
|
||||
|
||||
/**
|
||||
* The HTML filter class.
|
||||
|
|
@ -126,8 +127,8 @@ class HTMLFilter
|
|||
$config->set('URI.SafeIframeRegexp', MediaFilter::getIframeWhitelistRegex());
|
||||
|
||||
// Set the serializer path.
|
||||
$config->set('Cache.SerializerPath', RX_BASEDIR . 'files/cache/htmlpurifier');
|
||||
\FileHandler::makeDir(RX_BASEDIR . 'files/cache/htmlpurifier');
|
||||
$config->set('Cache.SerializerPath', \RX_BASEDIR . 'files/cache/htmlpurifier');
|
||||
Storage::createDirectory(\RX_BASEDIR . 'files/cache/htmlpurifier');
|
||||
|
||||
// Modify the HTML definition to support editor components and widgets.
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
|
|
@ -313,8 +314,8 @@ class HTMLFilter
|
|||
|
||||
// flexbox
|
||||
$info['display'] = new \HTMLPurifier_AttrDef_Enum(array(
|
||||
'block', 'flex', '-webkit-flex', 'inline', 'inline-block', 'inline-flex', '-webkit-inline-flex', 'inline-table',
|
||||
'list-item', 'run-in', 'compact', 'marker', 'table', 'table-row-group', 'table-header-group', 'table-footer-group',
|
||||
'block', 'flex', '-webkit-flex', 'inline', 'inline-block', 'inline-flex', '-webkit-inline-flex', 'inline-table',
|
||||
'list-item', 'run-in', 'compact', 'marker', 'table', 'table-row-group', 'table-header-group', 'table-footer-group',
|
||||
'table-row', 'table-column-group', 'table-column', 'table-cell', 'table-caption',
|
||||
'none', 'initial', 'inherit',
|
||||
));
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ class IpFilter
|
|||
return false;
|
||||
}
|
||||
|
||||
$cloudflare_ranges = (include RX_BASEDIR . 'common/defaults/cloudflare.php');
|
||||
$cloudflare_ranges = (include \RX_BASEDIR . 'common/defaults/cloudflare.php');
|
||||
foreach ($cloudflare_ranges as $cloudflare_range)
|
||||
{
|
||||
if (self::inRange($_SERVER['REMOTE_ADDR'], $cloudflare_range))
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ class MediaFilter
|
|||
*/
|
||||
protected static function _loadWhitelists($custom_whitelist = array())
|
||||
{
|
||||
$default_whitelist = (include RX_BASEDIR . 'common/defaults/whitelist.php');
|
||||
$default_whitelist = (include \RX_BASEDIR . 'common/defaults/whitelist.php');
|
||||
self::$_object_whitelist = array();
|
||||
self::$_iframe_whitelist = array();
|
||||
|
||||
|
|
|
|||
311
common/framework/formatter.php
Normal file
311
common/framework/formatter.php
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* The formatter class.
|
||||
*/
|
||||
class Formatter
|
||||
{
|
||||
/**
|
||||
* Options for text to HTML conversion.
|
||||
*/
|
||||
const TEXT_NEWLINE_AS_P = 1;
|
||||
const TEXT_DOUBLE_NEWLINE_AS_P = 2;
|
||||
|
||||
/**
|
||||
* Options for Markdown to HTML conversion.
|
||||
*/
|
||||
const MD_NEWLINE_AS_BR = 16;
|
||||
const MD_ENABLE_EXTRA = 128;
|
||||
|
||||
/**
|
||||
* Convert plain text to HTML.
|
||||
*
|
||||
* @param string $text
|
||||
* @param int $options (optional)
|
||||
* @return string
|
||||
*/
|
||||
public static function text2html($text, $options = 0)
|
||||
{
|
||||
// This option uses <p> instead of <br> to separate lines.
|
||||
if ($options & self::TEXT_NEWLINE_AS_P)
|
||||
{
|
||||
$lines = array_map('trim', explode("\n", escape(trim($text))));
|
||||
$result = '';
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
$result .= "<p>$line</p>\n";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
// This option uses <br> to separate lines and <p> to separate paragraphs.
|
||||
if ($options & self::TEXT_DOUBLE_NEWLINE_AS_P)
|
||||
{
|
||||
$lines = preg_replace('!(<br />)+\s*$!', '', nl2br(escape(trim($text))));
|
||||
$lines = preg_split('!(<br />\s*)+<br />!', $lines);
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
$result .= "<p>\n" . trim($line) . "\n</p>\n";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
// The default is to use <br> always.
|
||||
return nl2br(escape(trim($text))) . "<br />\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HTML to plain text.
|
||||
*
|
||||
* @param string $html
|
||||
* @return string
|
||||
*/
|
||||
public static function html2text($html)
|
||||
{
|
||||
// Add line breaks after <br> and <p> tags.
|
||||
$html = preg_replace('!<br[^>]*>\s*!i', "\n", $html);
|
||||
$html = preg_replace('!<p\b[^>]*>\s*!i', '', $html);
|
||||
$html = preg_replace('!</p[^>]*>\s*!i', "\n\n", $html);
|
||||
|
||||
// Encode links and images to preserve essential information.
|
||||
$html = preg_replace_callback('!<a\b[^>]*href="([^>"]+)"[^>]*>([^<]*)</a>!i', function($matches) {
|
||||
return trim($matches[2] . ' <' . $matches[1] . '>');
|
||||
}, $html);
|
||||
$html = preg_replace_callback('!<img\b[^>]*src="([^>"]+)"[^>]*>!i', function($matches) {
|
||||
$title = preg_match('!title="([^>"]+)"!i', $matches[0], $m) ? $m[1] : null;
|
||||
$title = $title ?: (preg_match('!alt="([^>"]+)"!i', $matches[0], $m) ? $m[1] : 'IMAGE');
|
||||
return trim('[' . $title . '] <' . $matches[1] . '>');
|
||||
}, $html);
|
||||
|
||||
// Strip all other HTML.
|
||||
$text = html_entity_decode(strip_tags($html));
|
||||
unset($html);
|
||||
|
||||
// Normalize whitespace and return.
|
||||
$text = str_replace("\r\n", "\n", $text);
|
||||
$text = preg_replace('/\n(?:\s*\n)+/', "\n\n", $text);
|
||||
return trim($text) . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Markdown to HTML.
|
||||
*
|
||||
* @param string $markdown
|
||||
* @param int $options (optional)
|
||||
* @return string
|
||||
*/
|
||||
public static function markdown2html($markdown, $options = 0)
|
||||
{
|
||||
if ($options & self::MD_NEWLINE_AS_BR)
|
||||
{
|
||||
$markdown = preg_replace('/(?<!\n)\n(?![\n\*\#\-])/', " \n", $markdown);
|
||||
}
|
||||
|
||||
if ($options & self::MD_ENABLE_EXTRA)
|
||||
{
|
||||
$class_name = '\\Michelf\\MarkdownExtra';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class_name = '\\Michelf\\Markdown';
|
||||
}
|
||||
|
||||
$html = $class_name::defaultTransform($markdown);
|
||||
return Filters\HTMLFilter::clean($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HTML to Markdown.
|
||||
*
|
||||
* @param string $html
|
||||
* @return string
|
||||
*/
|
||||
public static function html2markdown($html)
|
||||
{
|
||||
$converter = new \League\HTMLToMarkdown\HtmlConverter();
|
||||
$converter->getConfig()->setOption('bold_style', '**');
|
||||
$converter->getConfig()->setOption('italic_style', '_');
|
||||
$converter->getConfig()->setOption('strip_tags', true);
|
||||
return trim($converter->convert($html)) . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert BBCode to HTML.
|
||||
*
|
||||
* @param string $bbcode
|
||||
* @return string
|
||||
*/
|
||||
public static function bbcode($bbcode)
|
||||
{
|
||||
$parser = new \JBBCode\Parser;
|
||||
$parser->addCodeDefinitionSet(new \JBBCode\DefaultCodeDefinitionSet());
|
||||
|
||||
$builder = new \JBBCode\CodeDefinitionBuilder('quote', '<blockquote>{param}</blockquote>');
|
||||
$parser->addCodeDefinition($builder->build());
|
||||
$builder = new \JBBCode\CodeDefinitionBuilder('code', '<pre><code>{param}</code></pre>');
|
||||
$builder->setParseContent(false);
|
||||
$parser->addCodeDefinition($builder->build());
|
||||
|
||||
$parser->parse($bbcode);
|
||||
$html = $parser->getAsHtml();
|
||||
return Filters\HTMLFilter::clean($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply smart quotes and other stylistic enhancements to HTML.
|
||||
*
|
||||
* @param string $html
|
||||
* @return string
|
||||
*/
|
||||
public static function applySmartQuotes($html)
|
||||
{
|
||||
return \Michelf\SmartyPants::defaultTransform($html, 'qbBdDiew');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile LESS into CSS.
|
||||
*
|
||||
* @param string|array $source_filename
|
||||
* @param string $target_filename
|
||||
* @param array $variables (optional)
|
||||
* @parsm bool $minify (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function compileLESS($source_filename, $target_filename, $variables = array(), $minify = false)
|
||||
{
|
||||
// Get the cleaned and concatenated content.
|
||||
$content = self::_concatenate($source_filename, $target_filename);
|
||||
|
||||
// Compile!
|
||||
try
|
||||
{
|
||||
$less_compiler = new \lessc;
|
||||
$less_compiler->setFormatter($minify ? 'compressed' : 'lessjs');
|
||||
$less_compiler->setImportDir(array(dirname(is_array($source_filename) ? array_first($source_filename) : $source_filename)));
|
||||
if ($variables)
|
||||
{
|
||||
$less_compiler->setVariables($variables);
|
||||
}
|
||||
|
||||
$content = '@charset "UTF-8";' . "\n" . $less_compiler->compile($content) . "\n";
|
||||
$result = true;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$content = '/*' . "\n" . 'Error while compiling LESS:' . "\n" . $e->getMessage() . "\n" . '*/' . "\n";
|
||||
$result = false;
|
||||
}
|
||||
|
||||
// Save the result to the target file.
|
||||
Storage::write($target_filename, $content);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile SCSS into CSS.
|
||||
*
|
||||
* @param string|array $source_filename
|
||||
* @param string $target_filename
|
||||
* @param array $variables (optional)
|
||||
* @parsm bool $minify (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function compileSCSS($source_filename, $target_filename, $variables = array(), $minify = false)
|
||||
{
|
||||
// Get the cleaned and concatenated content.
|
||||
$content = self::_concatenate($source_filename, $target_filename);
|
||||
|
||||
// Compile!
|
||||
try
|
||||
{
|
||||
$scss_compiler = new \scssc;
|
||||
$scss_compiler->setFormatter($minify ? 'scss_formatter_compressed' : 'scss_formatter');
|
||||
$scss_compiler->setImportPaths(array(dirname(is_array($source_filename) ? array_first($source_filename) : $source_filename)));
|
||||
if ($variables)
|
||||
{
|
||||
$scss_compiler->setVariables($variables);
|
||||
}
|
||||
|
||||
$content = '@charset "UTF-8";' . "\n" . $scss_compiler->compile($content) . "\n";
|
||||
$result = true;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$content = '/*' . "\n" . 'Error while compiling SCSS:' . "\n" . $e->getMessage() . "\n" . '*/' . "\n";
|
||||
$result = false;
|
||||
}
|
||||
|
||||
// Save the result to the target file.
|
||||
Storage::write($target_filename, $content);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minify CSS.
|
||||
*
|
||||
* @param string|array $source_filename
|
||||
* @param string $target_filename
|
||||
* @return bool
|
||||
*/
|
||||
public static function minifyCSS($source_filename, $target_filename)
|
||||
{
|
||||
$minifier = new \MatthiasMullie\Minify\CSS($source_filename);
|
||||
$content = $minifier->execute($target_filename);
|
||||
Storage::write($target_filename, $content);
|
||||
return strlen($content) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minify JS.
|
||||
*
|
||||
* @param string|array $source_filename
|
||||
* @param string $target_filename
|
||||
* @return bool
|
||||
*/
|
||||
public static function minifyJS($source_filename, $target_filename)
|
||||
{
|
||||
$minifier = new \MatthiasMullie\Minify\JS($source_filename);
|
||||
$content = $minifier->execute($target_filename);
|
||||
Storage::write($target_filename, $content);
|
||||
return strlen($content) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* CSS concatenation subroutine for compileLESS() and compileSCSS().
|
||||
*
|
||||
* @param string|array $source_filename
|
||||
* @param string $target_filename
|
||||
* @return string
|
||||
*/
|
||||
protected static function _concatenate($source_filename, $target_filename)
|
||||
{
|
||||
$result = '';
|
||||
|
||||
if (!is_array($source_filename))
|
||||
{
|
||||
$source_filename = array($source_filename);
|
||||
}
|
||||
foreach ($source_filename as $filename)
|
||||
{
|
||||
$content = utf8_clean(file_get_contents($filename));
|
||||
$path_converter = new \MatthiasMullie\PathConverter\Converter($filename, $target_filename);
|
||||
$content = preg_replace_callback('/\burl\\(([^)]+)\\)/iU', function($matches) use ($path_converter) {
|
||||
$url = trim($matches[1], '\'"');
|
||||
if (!strlen($url) || $url[0] === '/')
|
||||
{
|
||||
return $matches[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'url("' . escape_dqstr($path_converter->convert($url)) . '")';
|
||||
}
|
||||
}, $content);
|
||||
unset($path_converter);
|
||||
$result .= trim($content) . "\n\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
78
common/framework/i18n.php
Normal file
78
common/framework/i18n.php
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* The i18n (internationalization) class.
|
||||
*/
|
||||
class i18n
|
||||
{
|
||||
/**
|
||||
* Constants for sorting.
|
||||
*/
|
||||
const SORT_CODE_2 = 2;
|
||||
const SORT_CODE_3 = 3;
|
||||
const SORT_CODE_NUMERIC = 4;
|
||||
const SORT_CCTLD = 5;
|
||||
const SORT_NAME_ENGLISH = 6;
|
||||
const SORT_NAME_KOREAN = 7;
|
||||
const SORT_NAME_NATIVE = 8;
|
||||
|
||||
/**
|
||||
* Get the list of all countries.
|
||||
*
|
||||
* @param int $sort_by
|
||||
* @return array
|
||||
*/
|
||||
public static function listCountries($sort_by = self::SORT_NAME_ENGLISH)
|
||||
{
|
||||
$countries = (include \RX_BASEDIR . 'common/defaults/countries.php');
|
||||
$result = array();
|
||||
|
||||
foreach ($countries as $country)
|
||||
{
|
||||
$result[$country['iso_3166_1_alpha3']] = (object)$country;
|
||||
}
|
||||
|
||||
switch ($sort_by)
|
||||
{
|
||||
case self::SORT_CODE_2:
|
||||
uasort($result, function($a, $b) {
|
||||
return strcmp($a->iso_3166_1_alpha2, $b->iso_3166_1_alpha2);
|
||||
});
|
||||
break;
|
||||
case self::SORT_CODE_3:
|
||||
uasort($result, function($a, $b) {
|
||||
return strcmp($a->iso_3166_1_alpha3, $b->iso_3166_1_alpha3);
|
||||
});
|
||||
break;
|
||||
case self::SORT_CODE_NUMERIC:
|
||||
uasort($result, function($a, $b) {
|
||||
return strcmp($a->iso_3166_1_numeric, $b->iso_3166_1_numeric);
|
||||
});
|
||||
break;
|
||||
case self::SORT_CCTLD:
|
||||
uasort($result, function($a, $b) {
|
||||
return strcmp($a->cctld, $b->cctld);
|
||||
});
|
||||
break;
|
||||
case self::SORT_NAME_ENGLISH:
|
||||
uasort($result, function($a, $b) {
|
||||
return strcmp($a->name_english, $b->name_english);
|
||||
});
|
||||
break;
|
||||
case self::SORT_NAME_KOREAN:
|
||||
uasort($result, function($a, $b) {
|
||||
return strcmp($a->name_korean, $b->name_korean);
|
||||
});
|
||||
break;
|
||||
case self::SORT_NAME_NATIVE:
|
||||
uasort($result, function($a, $b) {
|
||||
return strcmp($a->name_native, $b->name_native);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
453
common/framework/korea.php
Normal file
453
common/framework/korea.php
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* Class for validating Korea-specific information.
|
||||
*/
|
||||
class Korea
|
||||
{
|
||||
/**
|
||||
* Format a phone number.
|
||||
*
|
||||
* @param string $num
|
||||
* @return string
|
||||
*/
|
||||
public static function formatPhoneNumber($num)
|
||||
{
|
||||
// Remove all non-numbers.
|
||||
$num = preg_replace('/[^0-9]/', '', $num);
|
||||
|
||||
// Remove the country code.
|
||||
if (strncmp($num, '82', 2) === 0)
|
||||
{
|
||||
$num = substr($num, 2);
|
||||
if (strncmp($num, '0', 1) !== 0)
|
||||
{
|
||||
$num = '0' . $num;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply different format based on the number of digits.
|
||||
switch (strlen($num))
|
||||
{
|
||||
case 8:
|
||||
return substr($num, 0, 4) . '-' . substr($num, 4);
|
||||
case 9:
|
||||
return substr($num, 0, 2) . '-' . substr($num, 2, 3) . '-' . substr($num, 5);
|
||||
case 10:
|
||||
if (substr($num, 0, 2) === '02')
|
||||
{
|
||||
return substr($num, 0, 2) . '-' . substr($num, 2, 4) . '-' . substr($num, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
return substr($num, 0, 3) . '-' . substr($num, 3, 3) . '-' . substr($num, 6);
|
||||
}
|
||||
default:
|
||||
if (substr($num, 0, 4) === '0303' || substr($num, 0, 3) === '050')
|
||||
{
|
||||
return substr($num, 0, 4) . '-' . substr($num, 4, 3) . '-' . substr($num, 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
return substr($num, 0, 3) . '-' . substr($num, 3, 4) . '-' . substr($num, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Korean phone number contains a valid area code and the correct number of digits.
|
||||
*
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidPhoneNumber($num)
|
||||
{
|
||||
$num = str_replace('-', '', self::formatPhoneNumber($num));
|
||||
if (preg_match('/^1[0-9]{7}$/', $num))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (preg_match('/^02[2-9][0-9]{6,7}$/', $num))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (preg_match('/^0[13-8][0-9][2-9][0-9]{6,7}$/', $num))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Korean phone number is a mobile phone number.
|
||||
*
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidMobilePhoneNumber($num)
|
||||
{
|
||||
$num = str_replace('-', '', self::formatPhoneNumber($num));
|
||||
$len = strlen($num);
|
||||
return preg_match('/^01[016789][2-9][0-9]{6,7}$/', $num) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string is a valid resident registration number (주민등록번호)
|
||||
* or foreigner registration number (외국인등록번호).
|
||||
*
|
||||
* This method only checks the format.
|
||||
* It does not check that the number is actually in use.
|
||||
*
|
||||
* @param string $code
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidJuminNumber($code)
|
||||
{
|
||||
// Return false if the format is obviously wrong.
|
||||
if (!preg_match('/^[0-9]{6}-?[0-9]{7}$/', $code))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove hyphen.
|
||||
$code = str_replace('-', '', $code);
|
||||
|
||||
// Return false if the date of birth is in the future.
|
||||
if (in_array((int)($code[6]), array(3, 4, 7, 8)) && intval(substr($code, 0, 6), 10) > date('ymd'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate the checksum.
|
||||
$sum = 0;
|
||||
for ($i = 0; $i < 12; $i++)
|
||||
{
|
||||
$sum += $code[$i] * (($i % 8) + 2);
|
||||
}
|
||||
$checksum = (11 - ($sum % 11)) % 10;
|
||||
if (in_array((int)($code[6]), array(1, 2, 3, 4, 9, 0)))
|
||||
{
|
||||
return $checksum === (int)($code[12]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (substr($code, 7, 2) % 2 !== 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (($checksum + 2) % 10) === (int)($code[12]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string is a valid corporation registration number (법인등록번호).
|
||||
*
|
||||
* This method only checks the format.
|
||||
* It does not check that the number is actually in use.
|
||||
*
|
||||
* @param string $code
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidCorporationNumber($code)
|
||||
{
|
||||
// Return false if the format is obviously wrong.
|
||||
if (!preg_match('/^[0-9]{6}-?[0-9]{7}$/', $code))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove hyphen.
|
||||
$code = str_replace('-', '', $code);
|
||||
|
||||
// Calculate the checksum.
|
||||
$sum = 0;
|
||||
for ($i = 0; $i < 12; $i++)
|
||||
{
|
||||
$sum += $code[$i] * (($i % 2) + 1);
|
||||
}
|
||||
$checksum = (10 - ($sum % 10)) % 10;
|
||||
|
||||
// Check the 7th and 13th digits.
|
||||
if ($code[6] !== '0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return $checksum === (int)($code[12]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string is a valid business registration number (사업자등록번호).
|
||||
*
|
||||
* This method only checks the format.
|
||||
* It does not check that the number is actually in use.
|
||||
*
|
||||
* @param string $code
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidBusinessNumber($code)
|
||||
{
|
||||
// Return false if the format is obviously wrong.
|
||||
if (!preg_match('/^[0-9]{3}-?[0-9]{2}-?[0-9]{5}$/', $code))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove hyphen.
|
||||
$code = str_replace('-', '', $code);
|
||||
|
||||
// Calculate the checksum.
|
||||
$sum = 0;
|
||||
$sum += $code[0] + ($code[1] * 3) + ($code[2] * 7);
|
||||
$sum += $code[3] + ($code[4] * 3) + ($code[5] * 7);
|
||||
$sum += $code[6] + ($code[7] * 3) + ($code[8] * 5);
|
||||
$sum += floor(($code[8] * 5) / 10);
|
||||
$checksum = (10 - ($sum % 10)) % 10;
|
||||
|
||||
// Check the last digit.
|
||||
return $checksum === (int)($code[9]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given IP address is Korean.
|
||||
*
|
||||
* This method may return incorrect results if the IP allocation databases
|
||||
* (korea.ipv4.php, korea.ipv6.php) are out of date.
|
||||
*
|
||||
* @param string $ip
|
||||
* @return bool
|
||||
*/
|
||||
public static function isKoreanIP($ip)
|
||||
{
|
||||
// Extract the IPv4 address from an "IPv4-mapped IPv6" address.
|
||||
if (preg_match('/::ffff:(?:0+:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/', $ip, $matches)) $ip = $matches[1];
|
||||
|
||||
// Return false if the IP address is not in the right format.
|
||||
if (!filter_var($ip, \FILTER_VALIDATE_IP)) return false;
|
||||
|
||||
// Check IPv4.
|
||||
if (filter_var($ip, \FILTER_VALIDATE_IP, array('flags' => \FILTER_FLAG_IPV4)))
|
||||
{
|
||||
// Convert to integer.
|
||||
$ipnum = sprintf('%u', ip2long($ip));
|
||||
|
||||
// Treat local addresses as Korean.
|
||||
if ($ipnum >= 167772160 && $ipnum <= 184549375) return true; // 10.0.0.0/8
|
||||
if ($ipnum >= 2130706432 && $ipnum <= 2147483647) return true; // 127.0.0.0/8
|
||||
if ($ipnum >= 3232235520 && $ipnum <= 3232301055) return true; // 192.168.0.0/16
|
||||
if ($ipnum >= 2886729728 && $ipnum <= 2887778303) return true; // 172.16.0.0/20
|
||||
|
||||
// Check the IPv4 allocation database.
|
||||
$ranges = (include \RX_BASEDIR . 'common/defaults/korea.ipv4.php');
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if ($ipnum >= $range[0] && $ipnum <= $range[1]) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check IPv6.
|
||||
elseif (function_exists('inet_pton'))
|
||||
{
|
||||
// Convert to hexadecimal format.
|
||||
$ipbin = strtolower(bin2hex(inet_pton($ip)));
|
||||
|
||||
// Treat local addresses as Korean.
|
||||
if ($ipbin == '00000000000000000000000000000001') return true; // ::1
|
||||
if (preg_match('/^f(?:[cd]|e80{13})/', $ipbin)) return true; // fc00::/8, fd00::/8, fe80::/64
|
||||
|
||||
// Check the IPv6 allocation database.
|
||||
$ranges = (include \RX_BASEDIR . 'common/defaults/korea.ipv6.php');
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if (strncmp($ipbin, $range[0], 16) >= 0 && strncmp($ipbin, $range[1], 16) <= 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given email address is hosted by a Korean portal site.
|
||||
*
|
||||
* This can be used to tell which recipients may subscribe to the KISA RBL (kisarbl.or.kr).
|
||||
* If the domain is not found, this method returns false.
|
||||
*
|
||||
* @param string $domain
|
||||
* @param bool $clear_cache (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function isKoreanEmailAddress($email_address, $clear_cache = false)
|
||||
{
|
||||
// Clear the cache if requested.
|
||||
if ($clear_cache)
|
||||
{
|
||||
self::$_domain_cache = array();
|
||||
}
|
||||
|
||||
// Get the domain from the email address.
|
||||
if ($pos = strpos($email_address, '@'))
|
||||
{
|
||||
$domain = substr($email_address, $pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$domain = $email_address;
|
||||
}
|
||||
$domain = rtrim(strtolower($domain), '.');
|
||||
|
||||
// Return cached result if available.
|
||||
if (array_key_exists($domain, self::$_domain_cache))
|
||||
{
|
||||
return self::$_domain_cache[$domain];
|
||||
}
|
||||
|
||||
// Shortcut for known domains.
|
||||
if (in_array($domain, self::$known_korean))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = true;
|
||||
}
|
||||
if (in_array($domain, self::$known_foreign))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = false;
|
||||
}
|
||||
|
||||
// For unknown domains, check the MX record.
|
||||
$mx = self::_getDNSRecords($domain, \DNS_MX);
|
||||
|
||||
$i = 0;
|
||||
foreach ($mx as $mx)
|
||||
{
|
||||
$mx = rtrim($mx, '.');
|
||||
foreach (self::$known_korean as $portal)
|
||||
{
|
||||
if ($mx === $portal || ends_with('.' . $portal, $mx))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = true;
|
||||
}
|
||||
}
|
||||
foreach (self::$known_foreign as $portal)
|
||||
{
|
||||
if ($mx === $portal || ends_with('.' . $portal, $mx))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = false;
|
||||
}
|
||||
}
|
||||
foreach (self::_getDNSRecords($domain, \DNS_A) as $mx_ip)
|
||||
{
|
||||
return self::$_domain_cache[$domain] = self::isKoreanIP($mx_ip);
|
||||
}
|
||||
if (++$i > 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_domain_cache[$domain] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DNS records of a domain.
|
||||
*
|
||||
* @param string $domain
|
||||
* @param int $type
|
||||
* @return array
|
||||
*/
|
||||
protected static function _getDNSRecords($domain, $type)
|
||||
{
|
||||
$records = dns_get_record($domain, $type);
|
||||
if (!$records)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($records as $record)
|
||||
{
|
||||
if (isset($record['pri']) && isset($record['target']))
|
||||
{
|
||||
$result[intval($record['pri'])] = $record['target'];
|
||||
}
|
||||
elseif (isset($record['target']))
|
||||
{
|
||||
$result[] = $record['target'];
|
||||
}
|
||||
elseif (isset($record['ip']) || isset($record['ipv6']))
|
||||
{
|
||||
$result[] = isset($record['ip']) ? $record['ip'] : $record['ipv6'];
|
||||
}
|
||||
elseif (isset($record['txt']))
|
||||
{
|
||||
$result[] = $record['txt'];
|
||||
}
|
||||
}
|
||||
|
||||
ksort($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent multiple lookups for the same domain.
|
||||
*/
|
||||
protected static $_domain_cache = array();
|
||||
|
||||
/**
|
||||
* Domains known to be Korean and subscribed to the KISA RBL.
|
||||
*/
|
||||
public static $known_korean = array(
|
||||
'hanmail.net',
|
||||
'hanmail2.net',
|
||||
'daum.net',
|
||||
'paran.com',
|
||||
'tistory.com',
|
||||
'naver.com',
|
||||
'navercorp.com',
|
||||
'nate.com',
|
||||
'cyworld.com',
|
||||
'dreamwiz.com',
|
||||
'korea.com',
|
||||
'dreamx.com',
|
||||
'chol.com',
|
||||
'chollian.net',
|
||||
'hanmir.com',
|
||||
'hitel.com',
|
||||
'freechal.com',
|
||||
'empas.com',
|
||||
'empal.com',
|
||||
'hanafos.com',
|
||||
);
|
||||
|
||||
/**
|
||||
* Domains known to be foreign.
|
||||
*/
|
||||
public static $known_foreign = array(
|
||||
'gmail.com',
|
||||
'googlemail.com',
|
||||
'google.com',
|
||||
'yahoo.com',
|
||||
'yahoo.co.kr',
|
||||
'hotmail.com',
|
||||
'hotmail.co.kr',
|
||||
'live.com',
|
||||
'outlook.com',
|
||||
'msn.com',
|
||||
'me.com',
|
||||
'mac.com',
|
||||
'icloud.com',
|
||||
'facebook.com',
|
||||
'aol.com',
|
||||
'gmx.com',
|
||||
'mail.com',
|
||||
'fastmail.com',
|
||||
'fastmail.fm',
|
||||
'runbox.com',
|
||||
'inbox.com',
|
||||
'lycos.com',
|
||||
'zoho.com',
|
||||
);
|
||||
}
|
||||
|
|
@ -75,19 +75,19 @@ class Lang
|
|||
|
||||
if ($name === 'common')
|
||||
{
|
||||
$this->loadDirectory(RX_BASEDIR . 'common/lang', 'common');
|
||||
$this->loadDirectory(\RX_BASEDIR . 'common/lang', 'common');
|
||||
}
|
||||
elseif (file_exists(RX_BASEDIR . "plugins/$name/lang"))
|
||||
elseif (file_exists(\RX_BASEDIR . "plugins/$name/lang"))
|
||||
{
|
||||
$this->loadDirectory(RX_BASEDIR . "plugins/$name/lang", $name);
|
||||
$this->loadDirectory(\RX_BASEDIR . "plugins/$name/lang", $name);
|
||||
}
|
||||
elseif (file_exists(RX_BASEDIR . "modules/$name/lang"))
|
||||
elseif (file_exists(\RX_BASEDIR . "modules/$name/lang"))
|
||||
{
|
||||
$this->loadDirectory(RX_BASEDIR . "modules/$name/lang", $name);
|
||||
$this->loadDirectory(\RX_BASEDIR . "modules/$name/lang", $name);
|
||||
}
|
||||
elseif (file_exists(RX_BASEDIR . "addons/$name/lang"))
|
||||
elseif (file_exists(\RX_BASEDIR . "addons/$name/lang"))
|
||||
{
|
||||
$this->loadDirectory(RX_BASEDIR . "addons/$name/lang", $name);
|
||||
$this->loadDirectory(\RX_BASEDIR . "addons/$name/lang", $name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ class Lang
|
|||
*/
|
||||
public static function getSupportedList()
|
||||
{
|
||||
return (include RX_BASEDIR . 'common/defaults/lang.php');
|
||||
return (include \RX_BASEDIR . 'common/defaults/lang.php');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
152
common/framework/mime.php
Normal file
152
common/framework/mime.php
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* The MIME class.
|
||||
*/
|
||||
class MIME
|
||||
{
|
||||
/**
|
||||
* Get the MIME type for the given extension.
|
||||
*
|
||||
* @param string $extension
|
||||
* @return string
|
||||
*/
|
||||
public static function getTypeByExtension($extension)
|
||||
{
|
||||
$extension = strtolower($extension);
|
||||
return array_key_exists($extension, self::$_types) ? self::$_types[$extension] : self::$_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIME type for the given filename.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
public static function getTypeByFilename($filename)
|
||||
{
|
||||
$extension = strrchr($filename, '.');
|
||||
if ($extension === false) return self::$_default;
|
||||
$extension = strtolower(substr($extension, 1));
|
||||
return array_key_exists($extension, self::$_types) ? self::$_types[$extension] : self::$_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most common extension for the given MIME type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return string|false
|
||||
*/
|
||||
public static function getExtensionByType($type)
|
||||
{
|
||||
foreach (self::$_types as $extension => $mime)
|
||||
{
|
||||
if (!strncasecmp($type, $mime, strlen($type))) return $extension;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default MIME type for unknown extensions.
|
||||
*/
|
||||
protected static $_default = 'application/octet-stream';
|
||||
|
||||
/**
|
||||
* The list of known MIME types.
|
||||
*/
|
||||
protected static $_types = array(
|
||||
|
||||
// Text-based document formats.
|
||||
'html' => 'text/html',
|
||||
'htm' => 'text/html',
|
||||
'shtml' => 'text/html',
|
||||
'txt' => 'text/plain',
|
||||
'text' => 'text/plain',
|
||||
'log' => 'text/plain',
|
||||
'rtf' => 'text/rtf',
|
||||
'xml' => 'text/xml',
|
||||
'xsl' => 'text/xml',
|
||||
'css' => 'text/css',
|
||||
'csv' => 'text/csv',
|
||||
|
||||
// Binary document formats.
|
||||
'doc' => 'application/msword',
|
||||
'dot' => 'application/msword',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'odg' => 'application/vnd.oasis.opendocument.graphics',
|
||||
'odb' => 'application/vnd.oasis.opendocument.database',
|
||||
'pdf' => 'application/pdf',
|
||||
|
||||
// Images.
|
||||
'bmp' => 'image/bmp',
|
||||
'gif' => 'image/gif',
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'jpe' => 'image/jpeg',
|
||||
'png' => 'image/png',
|
||||
'svg' => 'image/svg+xml',
|
||||
'tiff' => 'image/tiff',
|
||||
'tif' => 'image/tiff',
|
||||
'ico' => 'image/vnd.microsoft.icon',
|
||||
|
||||
// Audio.
|
||||
'mid' => 'audio/midi',
|
||||
'midi' => 'audio/midi',
|
||||
'mpga' => 'audio/mpeg',
|
||||
'mp2' => 'audio/mpeg',
|
||||
'mp3' => 'audio/mpeg',
|
||||
'aif' => 'audio/x-aiff',
|
||||
'aiff' => 'audio/x-aiff',
|
||||
'ra' => 'audio/x-realaudio',
|
||||
'wav' => 'audio/x-wav',
|
||||
'ogg' => 'audio/ogg',
|
||||
|
||||
// Video.
|
||||
'avi' => 'video/x-msvideo',
|
||||
'flv' => 'video/x-flv',
|
||||
'mpeg' => 'video/mpeg',
|
||||
'mpg' => 'video/mpeg',
|
||||
'mpe' => 'video/mpeg',
|
||||
'mp4' => 'video/mpeg',
|
||||
'qt' => 'video/quicktime',
|
||||
'mov' => 'video/quicktime',
|
||||
'movie' => 'video/x-sgi-movie',
|
||||
'rv' => 'video/vnd.rn-realvideo',
|
||||
'dvi' => 'application/x-dvi',
|
||||
|
||||
// Other multimedia file formats.
|
||||
'psd' => 'application/x-photoshop',
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'ai' => 'application/postscript',
|
||||
'eps' => 'application/postscript',
|
||||
'ps' => 'application/postscript',
|
||||
'mif' => 'application/vnd.mif',
|
||||
'xul' => 'application/vnd.mozilla.xul+xml',
|
||||
|
||||
// Source code formats.
|
||||
'phps' => 'application/x-httpd-php-source',
|
||||
'js' => 'application/x-javascript',
|
||||
|
||||
// Archives.
|
||||
'bz2' => 'application/x-bzip',
|
||||
'gz' => 'application/x-gzip',
|
||||
'tar' => 'application/x-tar',
|
||||
'tgz' => 'application/x-tar',
|
||||
'gtar' => 'application/x-gtar',
|
||||
'rar' => 'application/x-rar-compressed',
|
||||
'zip' => 'application/x-zip',
|
||||
|
||||
// RFC822 email message.
|
||||
'eml' => 'message/rfc822',
|
||||
);
|
||||
}
|
||||
153
common/framework/pagination.php
Normal file
153
common/framework/pagination.php
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* The pagination class.
|
||||
*/
|
||||
class Pagination
|
||||
{
|
||||
/**
|
||||
* Count style constants.
|
||||
*/
|
||||
const COUNT_STYLE_NORMAL = 1;
|
||||
const COUNT_STYLE_CONTINUOUS = 2;
|
||||
|
||||
/**
|
||||
* Calculate the number of pages.
|
||||
*
|
||||
* @param int $total_items
|
||||
* @param int $items_per_page
|
||||
* @param int $minimum (optional)
|
||||
* @return int
|
||||
*/
|
||||
public static function countPages($total_items, $items_per_page, $minimum = 1)
|
||||
{
|
||||
if (!$items_per_page)
|
||||
{
|
||||
return (int)$minimum;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)max($minimum, ceil($total_items / $items_per_page));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create HTML for pagination.
|
||||
*
|
||||
* @param string $base_url ($PAGE will be replaced with the page number)
|
||||
* @param int $current_page
|
||||
* @param int $total_pages
|
||||
* @param int $count (optional)
|
||||
*/
|
||||
public static function createLinks($base_url, $total_pages, $current_page, $count = 10, $count_style = self::COUNT_STYLE_NORMAL)
|
||||
{
|
||||
// Only integers are allowed here.
|
||||
$current_page = (int)$current_page;
|
||||
$total_pages = (int)$total_pages;
|
||||
$count = (int)$count;
|
||||
|
||||
// Determine the range of pages to show.
|
||||
if ($count_style === self::COUNT_STYLE_NORMAL)
|
||||
{
|
||||
$last_shown = ceil($current_page / $count) * $count;
|
||||
$first_shown = max(1, $last_shown - $count + 1);
|
||||
if ($last_shown > $total_pages)
|
||||
{
|
||||
$last_shown = $total_pages;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$first_shown = $current_page - floor(($count - 1) / 2);
|
||||
if ($first_shown < 1)
|
||||
{
|
||||
$first_shown = 1;
|
||||
}
|
||||
$last_shown = $first_shown + $count - 1;
|
||||
if ($last_shown > $total_pages)
|
||||
{
|
||||
$last_shown = $total_pages;
|
||||
$first_shown = max(1, $last_shown - $count + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Open the <div> tag.
|
||||
$return = array('<div class="pagination">');
|
||||
|
||||
// Compose the link to the first page.
|
||||
if ($first_shown > 1)
|
||||
{
|
||||
if (strpos($base_url, '$PAGE') !== false)
|
||||
{
|
||||
$target_url = str_replace('$PAGE', 1, $base_url);
|
||||
}
|
||||
else
|
||||
{
|
||||
$target_url = $base_url . 1;
|
||||
}
|
||||
|
||||
$return[] = self::_composeLink($target_url, '<span class="arrow">«</span> <span class="page_number first_page">1</span>');
|
||||
$return[] = '<span class="ellipsis">...</span>';
|
||||
}
|
||||
|
||||
// Compose links for each page.
|
||||
for ($page = $first_shown; $page <= $last_shown; $page++)
|
||||
{
|
||||
if ($page == $current_page)
|
||||
{
|
||||
$opening_span = '<span class="page_number current_page">';
|
||||
}
|
||||
else
|
||||
{
|
||||
$opening_span = '<span class="page_number">';
|
||||
}
|
||||
|
||||
if (strpos($base_url, '$PAGE') !== false)
|
||||
{
|
||||
$target_url = str_replace('$PAGE', $page, $base_url);
|
||||
}
|
||||
else
|
||||
{
|
||||
$target_url = $base_url . $page;
|
||||
}
|
||||
|
||||
$return[] = self::_composeLink($target_url, $opening_span . $page . '</span>');
|
||||
}
|
||||
|
||||
// Compose the link to the last page.
|
||||
if ($last_shown < $total_pages)
|
||||
{
|
||||
if (strpos($base_url, '$PAGE') !== false)
|
||||
{
|
||||
$target_url = str_replace('$PAGE', $total_pages, $base_url);
|
||||
}
|
||||
else
|
||||
{
|
||||
$target_url = $base_url . $total_pages;
|
||||
}
|
||||
|
||||
$return[] = '<span class="ellipsis">...</span>';
|
||||
$return[] = self::_composeLink($target_url, '<span class="page_number last_page">' . $total_pages . '</span> <span class="arrow">»</span>');
|
||||
}
|
||||
|
||||
// Close the <div> tag.
|
||||
$return[] = '</div>';
|
||||
|
||||
// Return the completed HTML.
|
||||
return implode(' ', $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link creation subroutine.
|
||||
*
|
||||
* @param string $target_url
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
protected static function _composeLink($target_url, $content)
|
||||
{
|
||||
return '<a href="' . escape($target_url) . '">' . $content . '</a>';
|
||||
}
|
||||
}
|
||||
|
|
@ -19,9 +19,9 @@ class ConfigParser
|
|||
public static function convert()
|
||||
{
|
||||
// Load DB info file.
|
||||
if (file_exists(RX_BASEDIR . Config::$old_db_config_filename))
|
||||
if (file_exists(\RX_BASEDIR . Config::$old_db_config_filename))
|
||||
{
|
||||
include RX_BASEDIR . Config::$old_db_config_filename;
|
||||
include \RX_BASEDIR . Config::$old_db_config_filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -29,16 +29,16 @@ class ConfigParser
|
|||
}
|
||||
|
||||
// Load FTP info file.
|
||||
if (file_exists(RX_BASEDIR . Config::$old_ftp_config_filename))
|
||||
if (file_exists(\RX_BASEDIR . Config::$old_ftp_config_filename))
|
||||
{
|
||||
include RX_BASEDIR . Config::$old_ftp_config_filename;
|
||||
include \RX_BASEDIR . Config::$old_ftp_config_filename;
|
||||
}
|
||||
|
||||
// Load selected language file.
|
||||
if (file_exists(RX_BASEDIR . Config::$old_lang_config_filename))
|
||||
if (file_exists(\RX_BASEDIR . Config::$old_lang_config_filename))
|
||||
{
|
||||
$lang_selected = array();
|
||||
$lang_selected_raw = file_get_contents(RX_BASEDIR . Config::$old_lang_config_filename);
|
||||
$lang_selected_raw = file_get_contents(\RX_BASEDIR . Config::$old_lang_config_filename);
|
||||
$lang_selected_raw = array_map('trim', explode("\n", $lang_selected_raw));
|
||||
foreach ($lang_selected_raw as $lang_selected_item)
|
||||
{
|
||||
|
|
@ -59,7 +59,7 @@ class ConfigParser
|
|||
}
|
||||
|
||||
// Load defaults for the new configuration.
|
||||
$config = (include RX_BASEDIR . Config::$default_config_filename);
|
||||
$config = (include \RX_BASEDIR . Config::$default_config_filename);
|
||||
|
||||
// Convert database configuration.
|
||||
if (!isset($db_info->master_db))
|
||||
|
|
@ -184,7 +184,7 @@ class ConfigParser
|
|||
{
|
||||
$default_url = \Context::decodeIdna($default_url);
|
||||
}
|
||||
$config['url']['default'] = $default_url ?: (RX_SSL ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . \RX_BASEURL;
|
||||
$config['url']['default'] = $default_url ?: (\RX_SSL ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . \RX_BASEURL;
|
||||
$config['url']['http_port'] = $db_info->http_port ?: null;
|
||||
$config['url']['https_port'] = $db_info->https_port ?: null;
|
||||
$config['url']['ssl'] = $db_info->use_ssl ?: 'none';
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Rhymix\Framework\Parsers;
|
||||
|
||||
use Rhymix\Framework\Lang;
|
||||
use Rhymix\Framework\Storage;
|
||||
|
||||
/**
|
||||
* Lang parser class for XE compatibility.
|
||||
|
|
@ -32,7 +33,7 @@ class LangParser
|
|||
foreach ($files as $filename)
|
||||
{
|
||||
$new_filename = preg_replace('/\.lang\.php$/', '.php', str_replace('jp.lang', 'ja.lang', $filename));
|
||||
\FileHandler::rename($filename, $new_filename);
|
||||
Storage::move($filename, $new_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,7 +50,7 @@ class LangParser
|
|||
// Check if the cache file already exists.
|
||||
if ($output_filename === null)
|
||||
{
|
||||
$output_filename = RX_BASEDIR . 'files/cache/lang/' . md5($filename) . '.' . $language . '.php';
|
||||
$output_filename = \RX_BASEDIR . 'files/cache/lang/' . md5($filename) . '.' . $language . '.php';
|
||||
if (file_exists($output_filename) && filemtime($output_filename) > filemtime($filename))
|
||||
{
|
||||
return $output_filename;
|
||||
|
|
@ -60,7 +61,7 @@ class LangParser
|
|||
$xml = @simplexml_load_file($filename);
|
||||
if ($xml === false)
|
||||
{
|
||||
\FileHandler::writeFile($output_filename, '');
|
||||
Storage::write($output_filename, '');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +96,7 @@ class LangParser
|
|||
$buff .= '$lang->' . $key . ' = ' . var_export($value, true) . ";\n";
|
||||
}
|
||||
}
|
||||
\FileHandler::writeFile($output_filename, $buff);
|
||||
Storage::write($output_filename, $buff);
|
||||
return $output_filename;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,5 +7,476 @@ namespace Rhymix\Framework;
|
|||
*/
|
||||
class Storage
|
||||
{
|
||||
/**
|
||||
* Check if a path really exists.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function exists($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
clearstatcache(true, $path);
|
||||
return @file_exists($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path is a file.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isFile($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
return @self::exists($path) && @is_file($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path is an empty file.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isEmptyFile($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
return @self::exists($path) && @is_file($path) && (@filesize($path) == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the given path is a directory.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isDirectory($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
return @self::exists($path) && @is_dir($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path is an empty directory.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isEmptyDirectory($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
if (!self::isDirectory($path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$iterator = new \FilesystemIterator($path, \FilesystemIterator::SKIP_DOTS);
|
||||
return (iterator_count($iterator)) === 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path is a symbolic link.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSymlink($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
return @is_link($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path is a valid symbolic link.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidSymlink($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
return @is_link($path) && ($target = @readlink($path)) !== false && self::exists($target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path is readable.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isReadable($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
return @self::exists($path) && @is_readable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path is writable.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isWritable($path)
|
||||
{
|
||||
$path = rtrim($path, '/\\');
|
||||
return @self::exists($path) && @is_writable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of a file.
|
||||
*
|
||||
* This method returns the size of a file, or false on error.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return int|false
|
||||
*/
|
||||
public static function getSize($filename)
|
||||
{
|
||||
$filename = rtrim($filename, '/\\');
|
||||
if (self::exists($filename) && @is_file($filename) && @is_readable($filename))
|
||||
{
|
||||
return @filesize($filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content of a file.
|
||||
*
|
||||
* This method returns the content if it exists and is readable.
|
||||
* Otherwise, it returns false.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return string|false
|
||||
*/
|
||||
public static function read($filename)
|
||||
{
|
||||
$filename = rtrim($filename, '/\\');
|
||||
if (self::exists($filename) && @is_file($filename) && @is_readable($filename))
|
||||
{
|
||||
return @file_get_contents($filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write $content to a file.
|
||||
*
|
||||
* This method returns true on success and false on failure.
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $content
|
||||
* @param string $mode (optional)
|
||||
* @param int $perms (optional)
|
||||
* @return string|false
|
||||
*/
|
||||
public static function write($filename, $content, $mode = 'w', $perms = null)
|
||||
{
|
||||
$filename = rtrim($filename, '/\\');
|
||||
$destination_dir = dirname($filename);
|
||||
if (!self::exists($destination_dir))
|
||||
{
|
||||
$mkdir_success = self::createDirectory($destination_dir);
|
||||
if (!$mkdir_success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$flags = ($mode === 'a') ? (\FILE_APPEND | \LOCK_EX) : (\LOCK_EX);
|
||||
$write_success = @file_put_contents($filename, $content, $flags);
|
||||
$result = ($write_success === strlen($content)) ? true : false;
|
||||
@chmod($filename, ($perms === null ? (0666 & ~umask()) : $perms));
|
||||
if (function_exists('opcache_invalidate') && substr($filename, -4) === '.php')
|
||||
{
|
||||
@opcache_invalidate($filename, true);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy $source to $destination.
|
||||
*
|
||||
* This method returns true on success and false on failure.
|
||||
* If the destination permissions are not given, they will be copied from the source.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param int $destination_perms
|
||||
* @return bool
|
||||
*/
|
||||
public static function copy($source, $destination, $destination_perms = null)
|
||||
{
|
||||
$source = rtrim($source, '/\\');
|
||||
$destination = rtrim($destination, '/\\');
|
||||
if (!self::exists($source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$destination_dir = dirname($destination);
|
||||
if (!self::exists($destination_dir) && !self::createDirectory($destination_dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
elseif (self::isDirectory($destination))
|
||||
{
|
||||
$destination = $destination . '/' . basename($source);
|
||||
}
|
||||
|
||||
$copy_success = @copy($source, $destination);
|
||||
if (!$copy_success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($destination_perms === null)
|
||||
{
|
||||
@chmod($destination, 0777 & @fileperms($source));
|
||||
}
|
||||
else
|
||||
{
|
||||
@chmod($destination, $destination_perms);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move $source to $destination.
|
||||
*
|
||||
* This method returns true on success and false on failure.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @return bool
|
||||
*/
|
||||
public static function move($source, $destination)
|
||||
{
|
||||
$source = rtrim($source, '/\\');
|
||||
$destination = rtrim($destination, '/\\');
|
||||
if (!self::exists($source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$destination_dir = dirname($destination);
|
||||
if (!self::exists($destination_dir) && !self::createDirectory($destination_dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
elseif (self::isDirectory($destination))
|
||||
{
|
||||
$destination = $destination . '/' . basename($source);
|
||||
}
|
||||
|
||||
$result = @rename($source, $destination);
|
||||
if (function_exists('opcache_invalidate') && substr($source, -4) === '.php')
|
||||
{
|
||||
@opcache_invalidate($source, true);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file.
|
||||
*
|
||||
* This method returns true if the file exists and has been successfully
|
||||
* deleted, and false on any kind of failure.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return bool
|
||||
*/
|
||||
public static function delete($filename)
|
||||
{
|
||||
$filename = rtrim($filename, '/\\');
|
||||
$result = @self::exists($filename) && @is_file($filename) && @unlink($filename);
|
||||
if (function_exists('opcache_invalidate') && substr($filename, -4) === '.php')
|
||||
{
|
||||
@opcache_invalidate($filename, true);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a directory.
|
||||
*
|
||||
* @param string $dirname
|
||||
* @return bool
|
||||
*/
|
||||
public static function createDirectory($dirname, $mode = null)
|
||||
{
|
||||
$dirname = rtrim($dirname, '/\\');
|
||||
if ($mode === null)
|
||||
{
|
||||
$mode = 0777 & ~umask();
|
||||
}
|
||||
return @mkdir($dirname, $mode, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the list of files in a directory.
|
||||
*
|
||||
* @param string $dirname
|
||||
* @param bool $full_path (optional)
|
||||
* @param bool $skip_dotfiles (optional)
|
||||
* @param bool $skip_subdirs (optional)
|
||||
* @return array|false
|
||||
*/
|
||||
public static function readDirectory($dirname, $full_path = true, $skip_dotfiles = true, $skip_subdirs = true)
|
||||
{
|
||||
$dirname = rtrim($dirname, '/\\');
|
||||
if (!self::isDirectory($dirname))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$iterator = new \FilesystemIterator($dirname, \FilesystemIterator::CURRENT_AS_PATHNAME);
|
||||
}
|
||||
catch (\UnexpectedValueException $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($iterator as $fileinfo)
|
||||
{
|
||||
if (!$skip_subdirs || !is_dir($fileinfo))
|
||||
{
|
||||
$basename = basename($fileinfo);
|
||||
if (!$skip_dotfiles || $basename[0] !== '.')
|
||||
{
|
||||
$result[] = $full_path ? $fileinfo : $basename;
|
||||
}
|
||||
}
|
||||
}
|
||||
sort($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a directory recursively.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $exclude_regexp (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function copyDirectory($source, $destination, $exclude_regexp = null)
|
||||
{
|
||||
$source = rtrim($source, '/\\');
|
||||
$destination = rtrim($destination, '/\\');
|
||||
if (!self::isDirectory($source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!self::isDirectory($destination) && !self::createDirectory($destination))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$rdi_options = \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS;
|
||||
$rii_options = \RecursiveIteratorIterator::CHILD_FIRST;
|
||||
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, $rdi_options), $rii_options);
|
||||
|
||||
foreach ($iterator as $path)
|
||||
{
|
||||
$path_source = $path->getPathname();
|
||||
if (strpos($path_source, $source) !== 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ($exclude_regexp && preg_match($exclude_regexp, $path_source))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$path_destination = $destination . substr($path_source, strlen($source));
|
||||
if ($path->isDir())
|
||||
{
|
||||
$status = self::isDirectory($path_destination) || self::createDirectory($path_destination, $path->getPerms());
|
||||
if (!$status)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$status = self::copy($path_source, $path_destination, $path->getPerms());
|
||||
if (!$status)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a directory.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @return bool
|
||||
*/
|
||||
public static function moveDirectory($source, $destination)
|
||||
{
|
||||
return self::move($source, $destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a directory recursively.
|
||||
*
|
||||
* @param string $dirname
|
||||
* @param bool $delete_self (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteDirectory($dirname, $delete_self = true)
|
||||
{
|
||||
$dirname = rtrim($dirname, '/\\');
|
||||
if (!self::isDirectory($dirname))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$rdi_options = \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS;
|
||||
$rii_options = \RecursiveIteratorIterator::CHILD_FIRST;
|
||||
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dirname, $rdi_options), $rii_options);
|
||||
|
||||
foreach ($iterator as $path)
|
||||
{
|
||||
if ($path->isDir())
|
||||
{
|
||||
if (!@rmdir($path->getPathname()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!@unlink($path->getPathname()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_self)
|
||||
{
|
||||
return @rmdir($dirname);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
109
common/framework/timer.php
Normal file
109
common/framework/timer.php
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* The timer class.
|
||||
*/
|
||||
class Timer
|
||||
{
|
||||
/**
|
||||
* Timestamps are stored here.
|
||||
*/
|
||||
protected static $_timestamps = array();
|
||||
|
||||
/**
|
||||
* Start a timer.
|
||||
*
|
||||
* This method returns the current microtime.
|
||||
*
|
||||
* @param string $name (optional)
|
||||
* @return float
|
||||
*/
|
||||
public static function start($name = null)
|
||||
{
|
||||
$timestamp = microtime(true);
|
||||
|
||||
if ($name === null)
|
||||
{
|
||||
$name = 'anon-timer-' . $timestamp;
|
||||
}
|
||||
|
||||
self::$_timestamps[$name] = $timestamp;
|
||||
return $timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a timer and return the elapsed time.
|
||||
*
|
||||
* If the name is not given, the most recently started timer will be stopped.
|
||||
* If no timer has been started, this method returns false.
|
||||
*
|
||||
* @param string $name (optional)
|
||||
* @return float|false
|
||||
*/
|
||||
public static function stop($name = null)
|
||||
{
|
||||
$timestamp = microtime(true);
|
||||
$started_timestamp = 0;
|
||||
|
||||
if ($name === null)
|
||||
{
|
||||
if (count(self::$_timestamps))
|
||||
{
|
||||
$started_timestamp = array_pop(self::$_timestamps);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif (array_key_exists($name, self::$_timestamps))
|
||||
{
|
||||
$started_timestamp = self::$_timestamps[$name];
|
||||
unset(self::$_timestamps[$name]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $timestamp - $started_timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a timer and return the elapsed time in a human-readable format.
|
||||
*
|
||||
* If the name is not given, the most recently started timer will be stopped.
|
||||
* If no timer has been started, this method returns false.
|
||||
*
|
||||
* @param string $name (optional)
|
||||
* @return string|false
|
||||
*/
|
||||
public static function stopFormat($name = null)
|
||||
{
|
||||
$result = self::stop($name);
|
||||
if ($result === false) return $result;
|
||||
return number_format($result * 1000, 1, '.', ',') . 'ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns how much time has elapsed since Rhymix startup.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function sinceStartup()
|
||||
{
|
||||
return microtime(true) - \RX_MICROTIME;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns how much time has elapsed since startup in a human-readable format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function sinceStartupFormat()
|
||||
{
|
||||
return number_format((microtime(true) - \RX_MICROTIME) * 1000, 1, '.', ',') . 'ms';
|
||||
}
|
||||
}
|
||||
240
common/framework/ua.php
Normal file
240
common/framework/ua.php
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* The user-agent class.
|
||||
*/
|
||||
class UA
|
||||
{
|
||||
/**
|
||||
* Cache to prevent multiple lookups.
|
||||
*/
|
||||
protected static $_mobile_cache = array();
|
||||
protected static $_tablet_cache = array();
|
||||
protected static $_robot_cache = array();
|
||||
|
||||
/**
|
||||
* Check whether the current visitor is using a mobile device.
|
||||
*
|
||||
* @param string $ua (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function isMobile($ua = null)
|
||||
{
|
||||
// Get the User-Agent header if the caller did not specify $ua.
|
||||
if ($ua === null)
|
||||
{
|
||||
$ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
|
||||
$using_header = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$using_header = false;
|
||||
}
|
||||
|
||||
// If the User-Agent header is missing, it's probably not a mobile browser.
|
||||
if (is_null($ua))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look for headers that are only used in mobile browsers.
|
||||
if ($using_header && (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_X_OPERAMINI_PHONE_UA'])))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look up the cache.
|
||||
if (isset(self::$_mobile_cache[$ua]))
|
||||
{
|
||||
return self::$_mobile_cache[$ua];
|
||||
}
|
||||
|
||||
// Look for the 'mobile' keyword and common mobile platform names.
|
||||
if (preg_match('/android|ip(hone|ad|od)|blackberry|nokia|palm|mobile/i', $ua))
|
||||
{
|
||||
return self::$_mobile_cache[$ua] = true;
|
||||
}
|
||||
|
||||
// Look for common non-mobile OS names.
|
||||
if (preg_match('/windows|linux|os [x9]|bsd/i', $ua))
|
||||
{
|
||||
return self::$_mobile_cache[$ua] = false;
|
||||
}
|
||||
|
||||
// Look for other platform, manufacturer, and device names that are known to be mobile.
|
||||
if (preg_match('/kindle|opera (mini|mobi)|polaris|netfront|fennec|motorola|symbianos|webos/i', $ua))
|
||||
{
|
||||
return self::$_mobile_cache[$ua] = true;
|
||||
}
|
||||
if (preg_match('/s[pgc]h-|lgtelecom|sonyericsson|alcatel|vodafone|maemo|minimo|bada/i', $ua))
|
||||
{
|
||||
return self::$_mobile_cache[$ua] = true;
|
||||
}
|
||||
|
||||
// If we're here, it's probably not a mobile device.
|
||||
return self::$_mobile_cache[$ua] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the current visitor is using a tablet.
|
||||
*
|
||||
* @param string $ua (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function isTablet($ua = null)
|
||||
{
|
||||
// Get the User-Agent header if the caller did not specify $ua.
|
||||
$ua = $ua ?: (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null);
|
||||
|
||||
// If the User-Agent header is missing, it's probably not a tablet.
|
||||
if (is_null($ua))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look up the cache.
|
||||
if (isset(self::$_tablet_cache[$ua]))
|
||||
{
|
||||
return self::$_tablet_cache[$ua];
|
||||
}
|
||||
|
||||
// Check if the user-agent is mobile.
|
||||
if (!self::isMobile($ua))
|
||||
{
|
||||
return self::$_tablet_cache[$ua] = false;
|
||||
}
|
||||
|
||||
// Check for Android tablets without the 'mobile' keyword.
|
||||
if (stripos($ua, 'android') !== false && stripos($ua, 'mobile') === false)
|
||||
{
|
||||
return self::$_tablet_cache[$ua] = true;
|
||||
}
|
||||
|
||||
// Check for common tablet identifiers.
|
||||
if (preg_match('/tablet|pad\b|tab\b|\bgt-\d+|kindle|nook|playbook|webos|xoom/i', $ua))
|
||||
{
|
||||
return self::$_tablet_cache[$ua] = true;
|
||||
}
|
||||
|
||||
// If we're here, it's probably not a tablet.
|
||||
return self::$_tablet_cache[$ua] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the current visitor is a robot.
|
||||
*
|
||||
* @param string $ua (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRobot($ua = null)
|
||||
{
|
||||
// Get the User-Agent header if the caller did not specify $ua.
|
||||
$ua = $ua ?: (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null);
|
||||
|
||||
// If the User-Agent header is missing, it's probably not a robot.
|
||||
if (is_null($ua))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look up the cache.
|
||||
if (isset(self::$_robot_cache[$ua]))
|
||||
{
|
||||
return self::$_robot_cache[$ua];
|
||||
}
|
||||
|
||||
// Look for common search engine names and the 'bot' keyword.
|
||||
if (preg_match('/bot|slurp|facebook(externalhit|scraper)|ia_archiver|ask jeeves|teoma|baidu|daumoa|lycos|pingdom/i', $ua))
|
||||
{
|
||||
return self::$_robot_cache[$ua] = true;
|
||||
}
|
||||
|
||||
// If we're here, it's probably not a robot.
|
||||
return self::$_robot_cache[$ua] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method parses the User-Agent string to guess what kind of browser it is.
|
||||
*
|
||||
* @param string $ua (optional)
|
||||
* @return object
|
||||
*/
|
||||
public static function getBrowserInfo($ua = null)
|
||||
{
|
||||
// Get the User-Agent header if the caller did not specify $ua.
|
||||
$ua = $ua ?: (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null);
|
||||
|
||||
// Initialize the result.
|
||||
$result = (object)array(
|
||||
'browser' => null,
|
||||
'version' => null,
|
||||
'os' => null,
|
||||
'is_mobile' => null,
|
||||
'is_tablet' => null,
|
||||
);
|
||||
if (is_null($ua))
|
||||
{
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Try to guess the OS.
|
||||
if (preg_match('#(Windows|Android|Linux|iOS|OS X|Macintosh)#i', $ua, $matches))
|
||||
{
|
||||
if ($matches[1] === 'Linux' && strpos($ua, 'Android') !== false)
|
||||
{
|
||||
$matches[1] = 'Android';
|
||||
}
|
||||
if ($matches[1] === 'Macintosh' && strpos($ua, 'OS X') !== false)
|
||||
{
|
||||
$matches[1] = 'OS X';
|
||||
}
|
||||
$result->os = $matches[1];
|
||||
}
|
||||
|
||||
// Fill in miscellaneous fields.
|
||||
$result->is_mobile = self::isMobile($ua);
|
||||
$result->is_tablet = self::isTablet($ua);
|
||||
|
||||
// Try to match some of the most common browsers.
|
||||
if (preg_match('#Android ([0-9]+\\.[0-9]+)#', $ua, $matches) && strpos($ua, 'Chrome') === false)
|
||||
{
|
||||
$result->browser = 'Android';
|
||||
$result->version = $matches[1];
|
||||
return $result;
|
||||
}
|
||||
if (preg_match('#Edge/([0-9]+\\.)#', $ua, $matches))
|
||||
{
|
||||
$result->browser = 'Edge';
|
||||
$result->version = $matches[1] . '0';
|
||||
return $result;
|
||||
}
|
||||
if (preg_match('#Trident/([0-9]+)\\.[0-9]+#', $ua, $matches))
|
||||
{
|
||||
$result->browser = 'IE';
|
||||
$result->version = ($matches[1] + 4) . '.0';
|
||||
return $result;
|
||||
}
|
||||
if (preg_match('#(MSIE|Chrome|Firefox|Safari)[ /:]([0-9]+\\.[0-9]+)#', $ua, $matches))
|
||||
{
|
||||
$result->browser = $matches[1] === 'MSIE' ? 'IE' : $matches[1];
|
||||
$result->version = $matches[2];
|
||||
return $result;
|
||||
}
|
||||
if (preg_match('#^Opera/.+(?:Opera |Version/)([0-9]+\\.[0-9]+)$#', $ua, $matches))
|
||||
{
|
||||
$result->browser = 'Opera';
|
||||
$result->version = $matches[1];
|
||||
return $result;
|
||||
}
|
||||
if (preg_match('#(?:Konqueror|KHTML)/([0-9]+\\.[0-9]+)$#', $ua, $matches))
|
||||
{
|
||||
$result->browser = 'Konqueror';
|
||||
$result->version = $matches[1];
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
@ -519,6 +519,27 @@ function utf8_check($str)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove BOM and invalid UTF-8 sequences from file content.
|
||||
*
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
function utf8_clean($str)
|
||||
{
|
||||
if (strlen($str) >= 3 && substr($str, 0, 3) === "\xEF\xBB\xBF")
|
||||
{
|
||||
$str = substr($str, 3);
|
||||
}
|
||||
|
||||
if (!utf8_check($str))
|
||||
{
|
||||
$str = @iconv('UTF-8', 'UTF-8//IGNORE', $str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode UTF-8 characters outside of the Basic Multilingual Plane in the &#xxxxxx format.
|
||||
* This allows emoticons and other characters to be stored in MySQL without utf8mb4 support.
|
||||
|
|
|
|||
|
|
@ -999,8 +999,7 @@ function json_encode2($data)
|
|||
*/
|
||||
function isCrawler($agent = NULL)
|
||||
{
|
||||
$agent = $agent ?: $_SERVER['HTTP_USER_AGENT'];
|
||||
return (bool)preg_match('@bot|crawl|sp[iy]der|https?://|google|yahoo|slurp|yeti|daum|teoma|fish|hanrss|facebook|yandex|infoseek|askjeeves|stackrambler@i', $agent);
|
||||
return Rhymix\Framework\UA::isRobot($agent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,39 +1,44 @@
|
|||
{
|
||||
"name": "rhymix/rhymix",
|
||||
"description": "Rhymix",
|
||||
"homepage": "https://www.rhymix.org",
|
||||
"license": "GPL-2.0+",
|
||||
"type": "project",
|
||||
"authors": [
|
||||
{ "name": "Rhymix Developers and Contributors", "email": "devops@rhymix.org" },
|
||||
{ "name": "NAVER", "email": "developers@xpressengine.com" }
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"ext-curl": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-mcrypt": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-xml": "*",
|
||||
"defuse/php-encryption": "1.2.1",
|
||||
"ezyang/htmlpurifier": "4.7.*",
|
||||
"firephp/firephp-core": "0.4.0",
|
||||
"hautelook/phpass": "0.3.*",
|
||||
"matthiasmullie/minify": "1.3.*",
|
||||
"michelf/php-markdown": "1.5.*",
|
||||
"rmccue/requests": "1.6.*",
|
||||
"sunra/php-simple-html-dom-parser": "1.5.*",
|
||||
"name": "rhymix/rhymix",
|
||||
"description": "Rhymix",
|
||||
"homepage": "https://www.rhymix.org",
|
||||
"license": "GPL-2.0+",
|
||||
"type": "project",
|
||||
"authors": [
|
||||
{ "name": "Rhymix Developers and Contributors", "email": "devops@rhymix.org" },
|
||||
{ "name": "NAVER", "email": "developers@xpressengine.com" }
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"ext-curl": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-mcrypt": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-xml": "*",
|
||||
"defuse/php-encryption": "1.2.1",
|
||||
"ezyang/htmlpurifier": "4.7.*",
|
||||
"firephp/firephp-core": "0.4.0",
|
||||
"hautelook/phpass": "0.3.*",
|
||||
"jbbcode/jbbcode": "1.3.*",
|
||||
"leafo/lessphp": "0.5.*",
|
||||
"leafo/scssphp": "0.4.*",
|
||||
"league/html-to-markdown": "4.2.*",
|
||||
"matthiasmullie/minify": "1.3.*",
|
||||
"michelf/php-markdown": "1.6.*",
|
||||
"michelf/php-smartypants": "1.6.0-beta1",
|
||||
"rmccue/requests": "1.6.*",
|
||||
"sunra/php-simple-html-dom-parser": "1.5.*",
|
||||
"swiftmailer/swiftmailer": "5.4.*",
|
||||
"true/punycode": "2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"php": ">=5.4.0",
|
||||
"codeception/codeception": "2.1.*",
|
||||
"codeception/verify": "0.3.*",
|
||||
"codeception/specify": "0.4.*"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"php": ">=5.4.0",
|
||||
"codeception/codeception": "2.1.*",
|
||||
"codeception/verify": "0.3.*",
|
||||
"codeception/specify": "0.4.*"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
288
composer.lock
generated
288
composer.lock
generated
|
|
@ -4,8 +4,8 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "9b062f27815a9b2ef1e700b4664ee864",
|
||||
"content-hash": "69345a9112733f99c09fa298ba72fa22",
|
||||
"hash": "61ea4cb999dbb61cd01ba1a4ede5ead6",
|
||||
"content-hash": "ec214228f19d828ce0ea5feeb0a72aba",
|
||||
"packages": [
|
||||
{
|
||||
"name": "defuse/php-encryption",
|
||||
|
|
@ -176,6 +176,213 @@
|
|||
],
|
||||
"time": "2012-08-31 00:00:00"
|
||||
},
|
||||
{
|
||||
"name": "jbbcode/jbbcode",
|
||||
"version": "v1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jbowens/jBBCode.git",
|
||||
"reference": "645b6a1c0afa92b7d029d3417ebd8b60a5c578b3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jbowens/jBBCode/zipball/645b6a1c0afa92b7d029d3417ebd8b60a5c578b3",
|
||||
"reference": "645b6a1c0afa92b7d029d3417ebd8b60a5c578b3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "3.7.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"JBBCode": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jackson Owens",
|
||||
"email": "jackson_owens@alumni.brown.edu",
|
||||
"homepage": "http://jbowens.org/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A lightweight but extensible BBCode parser written in PHP 5.3.",
|
||||
"homepage": "http://jbbcode.com/",
|
||||
"keywords": [
|
||||
"BB",
|
||||
"bbcode"
|
||||
],
|
||||
"time": "2014-07-06 05:48:20"
|
||||
},
|
||||
{
|
||||
"name": "leafo/lessphp",
|
||||
"version": "v0.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/leafo/lessphp.git",
|
||||
"reference": "0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/leafo/lessphp/zipball/0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283",
|
||||
"reference": "0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"lessc.inc.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT",
|
||||
"GPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Leaf Corcoran",
|
||||
"email": "leafot@gmail.com",
|
||||
"homepage": "http://leafo.net"
|
||||
}
|
||||
],
|
||||
"description": "lessphp is a compiler for LESS written in PHP.",
|
||||
"homepage": "http://leafo.net/lessphp/",
|
||||
"time": "2014-11-24 18:39:20"
|
||||
},
|
||||
{
|
||||
"name": "leafo/scssphp",
|
||||
"version": "v0.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/leafo/scssphp.git",
|
||||
"reference": "78a6f27aa4eaf70bb3ff4d13b639bab71fdaf47a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/leafo/scssphp/zipball/78a6f27aa4eaf70bb3ff4d13b639bab71fdaf47a",
|
||||
"reference": "78a6f27aa4eaf70bb3ff4d13b639bab71fdaf47a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"kherge/box": "~2.5",
|
||||
"phpunit/phpunit": "~3.7",
|
||||
"squizlabs/php_codesniffer": "~2.3"
|
||||
},
|
||||
"bin": [
|
||||
"bin/pscss"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"classmap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Leafo\\ScssPhp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Leaf Corcoran",
|
||||
"email": "leafot@gmail.com",
|
||||
"homepage": "http://leafo.net"
|
||||
}
|
||||
],
|
||||
"description": "scssphp is a compiler for SCSS written in PHP.",
|
||||
"homepage": "http://leafo.github.io/scssphp/",
|
||||
"keywords": [
|
||||
"css",
|
||||
"less",
|
||||
"sass",
|
||||
"scss",
|
||||
"stylesheet"
|
||||
],
|
||||
"time": "2015-11-09 14:44:09"
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "4.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/html-to-markdown.git",
|
||||
"reference": "9a5becc8c6b520920fb846afefcfd7faf4c31712"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/9a5becc8c6b520920fb846afefcfd7faf4c31712",
|
||||
"reference": "9a5becc8c6b520920fb846afefcfd7faf4c31712",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-xml": "*",
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikehaertl/php-shellcommand": "~1.1.0",
|
||||
"phpunit/phpunit": "4.*",
|
||||
"scrutinizer/ocular": "~1.1"
|
||||
},
|
||||
"bin": [
|
||||
"bin/html-to-markdown"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\HTMLToMarkdown\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "http://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Nick Cernis",
|
||||
"email": "nick@cern.is",
|
||||
"homepage": "http://modernnerd.net",
|
||||
"role": "Original Author"
|
||||
}
|
||||
],
|
||||
"description": "An HTML-to-markdown conversion helper for PHP",
|
||||
"homepage": "https://github.com/thephpleague/html-to-markdown",
|
||||
"keywords": [
|
||||
"html",
|
||||
"markdown"
|
||||
],
|
||||
"time": "2016-02-01 16:49:02"
|
||||
},
|
||||
{
|
||||
"name": "matthiasmullie/minify",
|
||||
"version": "1.3.34",
|
||||
|
|
@ -284,16 +491,16 @@
|
|||
},
|
||||
{
|
||||
"name": "michelf/php-markdown",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/michelf/php-markdown.git",
|
||||
"reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9"
|
||||
"reference": "156e56ee036505ec637d761ee62dc425d807183c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/e1aabe18173231ebcefc90e615565742fc1c7fd9",
|
||||
"reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9",
|
||||
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c",
|
||||
"reference": "156e56ee036505ec637d761ee62dc425d807183c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -315,15 +522,15 @@
|
|||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "John Gruber",
|
||||
"homepage": "http://daringfireball.net/"
|
||||
},
|
||||
{
|
||||
"name": "Michel Fortin",
|
||||
"email": "michel.fortin@michelf.ca",
|
||||
"homepage": "https://michelf.ca/",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "John Gruber",
|
||||
"homepage": "https://daringfireball.net/"
|
||||
}
|
||||
],
|
||||
"description": "PHP Markdown",
|
||||
|
|
@ -331,7 +538,62 @@
|
|||
"keywords": [
|
||||
"markdown"
|
||||
],
|
||||
"time": "2015-03-01 12:03:08"
|
||||
"time": "2015-12-24 01:37:31"
|
||||
},
|
||||
{
|
||||
"name": "michelf/php-smartypants",
|
||||
"version": "1.6.0-beta1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/michelf/php-smartypants.git",
|
||||
"reference": "c0465c6d4c5ab853c2fa45df6c10bce7e35cc137"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/michelf/php-smartypants/zipball/c0465c6d4c5ab853c2fa45df6c10bce7e35cc137",
|
||||
"reference": "c0465c6d4c5ab853c2fa45df6c10bce7e35cc137",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-lib": "1.6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Michelf": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michel Fortin",
|
||||
"email": "michel.fortin@michelf.ca",
|
||||
"homepage": "http://michelf.ca/",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "John Gruber",
|
||||
"homepage": "http://daringfireball.net/"
|
||||
}
|
||||
],
|
||||
"description": "PHP SmartyPants",
|
||||
"homepage": "http://michelf.ca/projects/php-smartypants/",
|
||||
"keywords": [
|
||||
"dashes",
|
||||
"quotes",
|
||||
"spaces",
|
||||
"typographer",
|
||||
"typography"
|
||||
],
|
||||
"time": "2013-07-31 18:13:10"
|
||||
},
|
||||
{
|
||||
"name": "rmccue/requests",
|
||||
|
|
@ -528,7 +790,9 @@
|
|||
"packages-dev": null,
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {
|
||||
"michelf/php-smartypants": 10
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
|
|
|||
|
|
@ -1098,7 +1098,11 @@ class documentController extends document
|
|||
function updateReadedCount(&$oDocument)
|
||||
{
|
||||
// Pass if Crawler access
|
||||
if(isCrawler()) return false;
|
||||
if (\Rhymix\Framework\UA::isRobot())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$oDocumentModel = getModel('document');
|
||||
$config = $oDocumentModel->getDocumentConfig();
|
||||
|
||||
|
|
|
|||
6
tests/_data/formatter/bbcode.source.txt
Normal file
6
tests/_data/formatter/bbcode.source.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
This is the first paragraph.
|
||||
It contains [b]bold[/b] [i]italic[/i] text.
|
||||
|
||||
[quote]This is quoted text.[/quote]
|
||||
|
||||
This example belongs to the test suite for [url="https://www.rhymix.org"]Rhymix[/url].
|
||||
6
tests/_data/formatter/bbcode.target.html
Normal file
6
tests/_data/formatter/bbcode.target.html
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
This is the first paragraph.
|
||||
It contains <strong>bold</strong> <em>italic</em> text.
|
||||
|
||||
<blockquote>This is quoted text.</blockquote>
|
||||
|
||||
This example belongs to the test suite for <a href="https://www.rhymix.org">Rhymix</a>.
|
||||
13
tests/_data/formatter/html2markdown.source.html
Normal file
13
tests/_data/formatter/html2markdown.source.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<p>This is a Markdown document.
|
||||
These lines belong in the same paragraph.
|
||||
Markdown usually ignores single line breaks.
|
||||
</p>
|
||||
|
||||
<p>This is a <a href="foobar.html" title="title">link</a>.<br />
|
||||
This is an <img src="foobar.jpg" title="image" alt="alt" />.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>This is a list.</li>
|
||||
<li>It has two items.</li>
|
||||
</ul>
|
||||
7
tests/_data/formatter/html2markdown.target.md
Normal file
7
tests/_data/formatter/html2markdown.target.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
This is a Markdown document. These lines belong in the same paragraph. Markdown usually ignores single line breaks.
|
||||
|
||||
This is a [link](foobar.html "title").
|
||||
This is an .
|
||||
|
||||
- This is a list.
|
||||
- It has two items.
|
||||
13
tests/_data/formatter/html2text.source.html
Normal file
13
tests/_data/formatter/html2text.source.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<p>
|
||||
This is a sample text file.<br />
|
||||
This is a paragraph with multiple lines.<br />
|
||||
This is the third line.
|
||||
</p>
|
||||
<p>
|
||||
This is another paragraph.
|
||||
</p>
|
||||
<p>
|
||||
This is a <span>SPAN</span> element that will be stripped away.<br />
|
||||
This is a <a href="foobar.html">link</a> that will be preserved.<br />
|
||||
This is an <img src="test.jpg" alt="Image Title" /> that will be preserved.<br />
|
||||
</p>
|
||||
9
tests/_data/formatter/html2text.target.txt
Normal file
9
tests/_data/formatter/html2text.target.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
This is a sample text file.
|
||||
This is a paragraph with multiple lines.
|
||||
This is the third line.
|
||||
|
||||
This is another paragraph.
|
||||
|
||||
This is a SPAN element that will be stripped away.
|
||||
This is a link <foobar.html> that will be preserved.
|
||||
This is an [Image Title] <test.jpg> that will be preserved.
|
||||
3
tests/_data/formatter/less.source1.less
Normal file
3
tests/_data/formatter/less.source1.less
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.myfunction(@size) {
|
||||
margin: @size;
|
||||
}
|
||||
7
tests/_data/formatter/less.source2.less
Normal file
7
tests/_data/formatter/less.source2.less
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
.rhymix {
|
||||
color: @foo;
|
||||
background: url('foo/bar.jpg');
|
||||
span {
|
||||
.myfunction(@bar);
|
||||
}
|
||||
}
|
||||
9
tests/_data/formatter/less.target1.css
Normal file
9
tests/_data/formatter/less.target1.css
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
@charset "UTF-8";
|
||||
.rhymix {
|
||||
color: #123456;
|
||||
background: url("../_data/formatter/foo/bar.jpg");
|
||||
}
|
||||
.rhymix span {
|
||||
margin: 320px;
|
||||
}
|
||||
|
||||
2
tests/_data/formatter/less.target2.css
Normal file
2
tests/_data/formatter/less.target2.css
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
@charset "UTF-8";
|
||||
.rhymix{color:#123456;background:url("../_data/formatter/foo/bar.jpg");}.rhymix span{margin:320px;}
|
||||
17
tests/_data/formatter/markdown2html.source.md
Normal file
17
tests/_data/formatter/markdown2html.source.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
This is a Markdown document.
|
||||
These lines belong in the same paragraph.
|
||||
Markdown usually ignores single line breaks.
|
||||
|
||||
This is an indented code segment.
|
||||
All Markdown variants will recognize it.
|
||||
|
||||
```
|
||||
This is a fenced code segment.
|
||||
Only Markdown Extra will recognize it.
|
||||
```
|
||||
|
||||
This is a [link](foobar.html).
|
||||
This is an .
|
||||
|
||||
- This is a list.
|
||||
- It has two items.
|
||||
17
tests/_data/formatter/markdown2html.target1.html
Normal file
17
tests/_data/formatter/markdown2html.target1.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<p>This is a Markdown document.
|
||||
These lines belong in the same paragraph.
|
||||
Markdown usually ignores single line breaks.</p>
|
||||
|
||||
<pre><code>This is an indented code segment.
|
||||
All Markdown variants will recognize it.
|
||||
</code></pre>
|
||||
|
||||
<p><code>This is a fenced code segment.
|
||||
Only Markdown Extra will recognize it.</code></p>
|
||||
|
||||
<p>This is a <a href="foobar.html">link</a>.
|
||||
This is an <img src="foobar.jpg" alt="image" />.</p>
|
||||
|
||||
<ul><li>This is a list.</li>
|
||||
<li>It has two items.</li>
|
||||
</ul>
|
||||
17
tests/_data/formatter/markdown2html.target2.html
Normal file
17
tests/_data/formatter/markdown2html.target2.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<p>This is a Markdown document.<br />
|
||||
These lines belong in the same paragraph.<br />
|
||||
Markdown usually ignores single line breaks.</p>
|
||||
|
||||
<pre><code>This is an indented code segment.
|
||||
All Markdown variants will recognize it.
|
||||
</code></pre>
|
||||
|
||||
<p><code>This is a fenced code segment.
|
||||
Only Markdown Extra will recognize it.</code></p>
|
||||
|
||||
<p>This is a <a href="foobar.html">link</a>.<br />
|
||||
This is an <img src="foobar.jpg" alt="image" />.</p>
|
||||
|
||||
<ul><li>This is a list. </li>
|
||||
<li>It has two items. </li>
|
||||
</ul>
|
||||
18
tests/_data/formatter/markdown2html.target3.html
Normal file
18
tests/_data/formatter/markdown2html.target3.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<p>This is a Markdown document.<br />
|
||||
These lines belong in the same paragraph.<br />
|
||||
Markdown usually ignores single line breaks.</p>
|
||||
|
||||
<pre><code>This is an indented code segment.
|
||||
All Markdown variants will recognize it.
|
||||
</code></pre>
|
||||
|
||||
<pre><code>This is a fenced code segment.
|
||||
Only Markdown Extra will recognize it.
|
||||
</code></pre>
|
||||
|
||||
<p>This is a <a href="foobar.html">link</a>.<br />
|
||||
This is an <img src="foobar.jpg" alt="image" />.</p>
|
||||
|
||||
<ul><li>This is a list. </li>
|
||||
<li>It has two items. </li>
|
||||
</ul>
|
||||
10
tests/_data/formatter/minify.source.css
Normal file
10
tests/_data/formatter/minify.source.css
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
@charset "UTF-8";
|
||||
.rhymix {
|
||||
background: url("foo/bar.jpg");
|
||||
}
|
||||
.wordpress {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.xpressengine {
|
||||
margin: 320px;
|
||||
}
|
||||
6
tests/_data/formatter/minify.source.js
Normal file
6
tests/_data/formatter/minify.source.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(function($) {
|
||||
$(".foo").click(function(event) {
|
||||
event.preventDefault();
|
||||
$(this).attr("bar", "baz");
|
||||
});
|
||||
})(jQuery);
|
||||
1
tests/_data/formatter/minify.target.css
Normal file
1
tests/_data/formatter/minify.target.css
Normal file
|
|
@ -0,0 +1 @@
|
|||
@charset "UTF-8";.rhymix{background:url(../_data/formatter/foo/bar.jpg)}.wordpress{border-radius:4px}.xpressengine{margin:320px}
|
||||
1
tests/_data/formatter/minify.target.js
Normal file
1
tests/_data/formatter/minify.target.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
(function($){$(".foo").click(function(event){event.preventDefault();$(this).attr("bar","baz")})})(jQuery)
|
||||
3
tests/_data/formatter/scss.source1.scss
Normal file
3
tests/_data/formatter/scss.source1.scss
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@mixin mymixin($size) {
|
||||
margin: $size;
|
||||
}
|
||||
7
tests/_data/formatter/scss.source2.scss
Normal file
7
tests/_data/formatter/scss.source2.scss
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
.rhymix {
|
||||
color: $foo;
|
||||
background: url('foo/bar.jpg');
|
||||
span {
|
||||
@include mymixin($bar);
|
||||
}
|
||||
}
|
||||
9
tests/_data/formatter/scss.target1.css
Normal file
9
tests/_data/formatter/scss.target1.css
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
@charset "UTF-8";
|
||||
.rhymix {
|
||||
color: #123456;
|
||||
background: url("../_data/formatter/foo/bar.jpg");
|
||||
}
|
||||
.rhymix span {
|
||||
margin: 320px;
|
||||
}
|
||||
|
||||
2
tests/_data/formatter/scss.target2.css
Normal file
2
tests/_data/formatter/scss.target2.css
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
@charset "UTF-8";
|
||||
.rhymix{color:#123456;background:url("../_data/formatter/foo/bar.jpg")}.rhymix span{margin:320px}
|
||||
2
tests/_data/formatter/smartypants.source.html
Normal file
2
tests/_data/formatter/smartypants.source.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<p>This paragraph contains "dumb quotes" and short -- dashes.</p>
|
||||
<p>This paragraph contains ``backtick quotes'' and 'long' --- dashes...</p>
|
||||
2
tests/_data/formatter/smartypants.target.html
Normal file
2
tests/_data/formatter/smartypants.target.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<p>This paragraph contains “dumb quotes” and short — dashes.</p>
|
||||
<p>This paragraph contains “backtick quotes” and ’long’ – dashes…</p>
|
||||
9
tests/_data/formatter/text2html.source.txt
Normal file
9
tests/_data/formatter/text2html.source.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
This is a sample text file.
|
||||
Some of these lines are close together.
|
||||
|
||||
Other lines are separated by two newlines.
|
||||
|
||||
|
||||
Or three newlines.
|
||||
This is a <p>tag</p> that will be escaped if encoded.
|
||||
Hello world!
|
||||
9
tests/_data/formatter/text2html.target1.html
Normal file
9
tests/_data/formatter/text2html.target1.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
This is a sample text file.<br />
|
||||
Some of these lines are close together.<br />
|
||||
<br />
|
||||
Other lines are separated by two newlines.<br />
|
||||
<br />
|
||||
<br />
|
||||
Or three newlines.<br />
|
||||
This is a <p>tag</p> that will be escaped if encoded.<br />
|
||||
Hello world!<br />
|
||||
9
tests/_data/formatter/text2html.target2.html
Normal file
9
tests/_data/formatter/text2html.target2.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<p>This is a sample text file.</p>
|
||||
<p>Some of these lines are close together.</p>
|
||||
<p></p>
|
||||
<p>Other lines are separated by two newlines.</p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p>Or three newlines.</p>
|
||||
<p>This is a <p>tag</p> that will be escaped if encoded.</p>
|
||||
<p>Hello world!</p>
|
||||
12
tests/_data/formatter/text2html.target3.html
Normal file
12
tests/_data/formatter/text2html.target3.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<p>
|
||||
This is a sample text file.<br />
|
||||
Some of these lines are close together.
|
||||
</p>
|
||||
<p>
|
||||
Other lines are separated by two newlines.
|
||||
</p>
|
||||
<p>
|
||||
Or three newlines.<br />
|
||||
This is a <p>tag</p> that will be escaped if encoded.<br />
|
||||
Hello world!
|
||||
</p>
|
||||
52
tests/unit/framework/CalendarTest.php
Normal file
52
tests/unit/framework/CalendarTest.php
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
class CalendarTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testGetMonthName()
|
||||
{
|
||||
$this->assertEquals('January', Rhymix\Framework\Calendar::getMonthName('01'));
|
||||
$this->assertEquals('October', Rhymix\Framework\Calendar::getMonthName('10'));
|
||||
$this->assertEquals('Nov', Rhymix\Framework\Calendar::getMonthName(11, false));
|
||||
$this->assertEquals('Dec', Rhymix\Framework\Calendar::getMonthName(12, false));
|
||||
}
|
||||
|
||||
public function testGetMonthStartDayOfWeek()
|
||||
{
|
||||
$this->assertEquals(5, Rhymix\Framework\Calendar::getMonthStartDayOfWeek(1, 2016));
|
||||
$this->assertEquals(1, Rhymix\Framework\Calendar::getMonthStartDayOfWeek(2, 2016));
|
||||
$this->assertEquals(2, Rhymix\Framework\Calendar::getMonthStartDayOfWeek(3, 2016));
|
||||
$this->assertEquals(5, Rhymix\Framework\Calendar::getMonthStartDayOfWeek(4, 2016));
|
||||
}
|
||||
|
||||
public function testGetMonthDays()
|
||||
{
|
||||
$this->assertEquals(30, Rhymix\Framework\Calendar::getMonthDays(11, 2015));
|
||||
$this->assertEquals(31, Rhymix\Framework\Calendar::getMonthDays(12, 2015));
|
||||
$this->assertEquals(31, Rhymix\Framework\Calendar::getMonthDays(1, 2016));
|
||||
$this->assertEquals(29, Rhymix\Framework\Calendar::getMonthDays(2, 2016));
|
||||
}
|
||||
|
||||
public function testGetMonthCalendar()
|
||||
{
|
||||
$target_201508 = array(
|
||||
array(null, null, null, null, null, null, 1),
|
||||
array(2, 3, 4, 5, 6, 7, 8),
|
||||
array(9, 10, 11, 12, 13, 14, 15),
|
||||
array(16, 17, 18, 19, 20, 21, 22),
|
||||
array(23, 24, 25, 26, 27, 28, 29),
|
||||
array(30, 31, null, null, null, null, null),
|
||||
);
|
||||
|
||||
$target_201603 = array(
|
||||
array(null, null, 1, 2, 3, 4, 5),
|
||||
array(6, 7, 8, 9, 10, 11, 12),
|
||||
array(13, 14, 15, 16, 17, 18, 19),
|
||||
array(20, 21, 22, 23, 24, 25, 26),
|
||||
array(27, 28, 29, 30, 31, null, null),
|
||||
array(null, null, null, null, null, null, null),
|
||||
);
|
||||
|
||||
$this->assertEquals($target_201508, Rhymix\Framework\Calendar::getMonthCalendar(8, 2015));
|
||||
$this->assertEquals($target_201603, Rhymix\Framework\Calendar::getMonthCalendar(3, 2016));
|
||||
}
|
||||
}
|
||||
134
tests/unit/framework/FormatterTest.php
Normal file
134
tests/unit/framework/FormatterTest.php
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
|
||||
class FormatterTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testText2HTML()
|
||||
{
|
||||
$text = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/text2html.source.txt');
|
||||
$html1 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/text2html.target1.html');
|
||||
$html2 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/text2html.target2.html');
|
||||
$html3 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/text2html.target3.html');
|
||||
|
||||
$this->assertEquals($html1, Rhymix\Framework\Formatter::text2html($text));
|
||||
$this->assertEquals($html2, Rhymix\Framework\Formatter::text2html($text, Rhymix\Framework\Formatter::TEXT_NEWLINE_AS_P));
|
||||
$this->assertEquals($html3, Rhymix\Framework\Formatter::text2html($text, Rhymix\Framework\Formatter::TEXT_DOUBLE_NEWLINE_AS_P));
|
||||
}
|
||||
|
||||
public function testHTML2Text()
|
||||
{
|
||||
$html = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/html2text.source.html');
|
||||
$text = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/html2text.target.txt');
|
||||
|
||||
$this->assertEquals($text, Rhymix\Framework\Formatter::html2text($html));
|
||||
}
|
||||
|
||||
public function testMarkdown2HTML()
|
||||
{
|
||||
$markdown = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/markdown2html.source.md');
|
||||
$html1 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/markdown2html.target1.html');
|
||||
$html2 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/markdown2html.target2.html');
|
||||
$html3 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/markdown2html.target3.html');
|
||||
|
||||
$this->assertEquals($html1, Rhymix\Framework\Formatter::markdown2html($markdown));
|
||||
$this->assertEquals($html2, Rhymix\Framework\Formatter::markdown2html($markdown, Rhymix\Framework\Formatter::MD_NEWLINE_AS_BR));
|
||||
$this->assertEquals($html3, Rhymix\Framework\Formatter::markdown2html($markdown, Rhymix\Framework\Formatter::MD_NEWLINE_AS_BR | Rhymix\Framework\Formatter::MD_ENABLE_EXTRA));
|
||||
}
|
||||
|
||||
public function testHTML2Markdown()
|
||||
{
|
||||
$html = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/html2markdown.source.html');
|
||||
$markdown = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/html2markdown.target.md');
|
||||
|
||||
$this->assertEquals($markdown, Rhymix\Framework\Formatter::html2markdown($html));
|
||||
}
|
||||
|
||||
public function testBBCode()
|
||||
{
|
||||
$bbcode = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/bbcode.source.txt');
|
||||
$html = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/bbcode.target.html');
|
||||
|
||||
$this->assertEquals($html, Rhymix\Framework\Formatter::bbcode($bbcode));
|
||||
}
|
||||
|
||||
public function testApplySmartQuotes()
|
||||
{
|
||||
$before = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/smartypants.source.html');
|
||||
$after = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/smartypants.target.html');
|
||||
|
||||
$this->assertEquals($after, Rhymix\Framework\Formatter::applySmartQuotes($before));
|
||||
}
|
||||
|
||||
public function testCompileLESS()
|
||||
{
|
||||
$sources = array(
|
||||
\RX_BASEDIR . 'tests/_data/formatter/less.source1.less',
|
||||
\RX_BASEDIR . 'tests/_data/formatter/less.source2.less',
|
||||
);
|
||||
$variables = array(
|
||||
'foo' => '#123456',
|
||||
'bar' => '320px',
|
||||
);
|
||||
|
||||
$real_target1 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/less.target1.css');
|
||||
$real_target2 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/less.target2.css');
|
||||
$test_target1 = \RX_BASEDIR . 'tests/_output/less.target1.css';
|
||||
$test_target2 = \RX_BASEDIR . 'tests/_output/less.target2.css';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Formatter::compileLESS($sources, $test_target1, $variables));
|
||||
$this->assertEquals($real_target1, file_get_contents($test_target1));
|
||||
$this->assertTrue(Rhymix\Framework\Formatter::compileLESS($sources, $test_target2, $variables, true));
|
||||
$this->assertEquals($real_target2, file_get_contents($test_target2));
|
||||
|
||||
unlink($test_target1);
|
||||
unlink($test_target2);
|
||||
}
|
||||
|
||||
public function testCompileSCSS()
|
||||
{
|
||||
$sources = array(
|
||||
\RX_BASEDIR . 'tests/_data/formatter/scss.source1.scss',
|
||||
\RX_BASEDIR . 'tests/_data/formatter/scss.source2.scss',
|
||||
);
|
||||
$variables = array(
|
||||
'foo' => '#123456',
|
||||
'bar' => '320px',
|
||||
);
|
||||
|
||||
$real_target1 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/scss.target1.css');
|
||||
$real_target2 = file_get_contents(\RX_BASEDIR . 'tests/_data/formatter/scss.target2.css');
|
||||
$test_target1 = \RX_BASEDIR . 'tests/_output/scss.target1.css';
|
||||
$test_target2 = \RX_BASEDIR . 'tests/_output/scss.target2.css';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Formatter::compileSCSS($sources, $test_target1, $variables));
|
||||
$this->assertEquals($real_target1, file_get_contents($test_target1));
|
||||
$this->assertTrue(Rhymix\Framework\Formatter::compileSCSS($sources, $test_target2, $variables, true));
|
||||
$this->assertEquals($real_target2, file_get_contents($test_target2));
|
||||
|
||||
unlink($test_target1);
|
||||
unlink($test_target2);
|
||||
}
|
||||
|
||||
public function testMinifyCSS()
|
||||
{
|
||||
$source = \RX_BASEDIR . 'tests/_data/formatter/minify.source.css';
|
||||
$real_target = \RX_BASEDIR . 'tests/_data/formatter/minify.target.css';
|
||||
$test_target = \RX_BASEDIR . 'tests/_output/minify.target.css';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Formatter::minifyCSS($source, $test_target));
|
||||
$this->assertEquals(file_get_contents($real_target), file_get_contents($test_target));
|
||||
|
||||
unlink($test_target);
|
||||
}
|
||||
|
||||
public function testMinifyJS()
|
||||
{
|
||||
$source = \RX_BASEDIR . 'tests/_data/formatter/minify.source.js';
|
||||
$real_target = \RX_BASEDIR . 'tests/_data/formatter/minify.target.js';
|
||||
$test_target = \RX_BASEDIR . 'tests/_output/minify.target.js';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Formatter::minifyJS($source, $test_target));
|
||||
$this->assertEquals(file_get_contents($real_target), file_get_contents($test_target));
|
||||
|
||||
unlink($test_target);
|
||||
}
|
||||
}
|
||||
107
tests/unit/framework/KoreaTest.php
Normal file
107
tests/unit/framework/KoreaTest.php
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
class KoreaTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testFormatPhoneNumber()
|
||||
{
|
||||
$this->assertEquals('1588-0000', Rhymix\Framework\Korea::formatPhoneNumber('1588-0000'));
|
||||
$this->assertEquals('02-345-6789', Rhymix\Framework\Korea::formatPhoneNumber('+82 23456789'));
|
||||
$this->assertEquals('02-3000-5000', Rhymix\Framework\Korea::formatPhoneNumber('0230005000'));
|
||||
$this->assertEquals('031-222-3333', Rhymix\Framework\Korea::formatPhoneNumber('82-0312-2233-33'));
|
||||
$this->assertEquals('031-2222-3333', Rhymix\Framework\Korea::formatPhoneNumber('03122223333'));
|
||||
$this->assertEquals('011-444-5555', Rhymix\Framework\Korea::formatPhoneNumber('011 444 5555'));
|
||||
$this->assertEquals('010-6666-7777', Rhymix\Framework\Korea::formatPhoneNumber('82+1066667777'));
|
||||
$this->assertEquals('0303-456-7890', Rhymix\Framework\Korea::formatPhoneNumber('03034567890'));
|
||||
$this->assertEquals('0505-987-6543', Rhymix\Framework\Korea::formatPhoneNumber('050-5987-6543'));
|
||||
$this->assertEquals('070-7432-1000', Rhymix\Framework\Korea::formatPhoneNumber('0707-432-1000'));
|
||||
}
|
||||
|
||||
public function testIsValidPhoneNumber()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('1588-0000'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('02-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('+82-2-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('+82-02-2345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('053-444-5555'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('053-4444-5555'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('011-444-5555'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('010-4444-5555'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('010-4444-55555'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('010-1234-5678'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('02-123-4567'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('02-123456'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('03-456-7890'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('090-9876-5432'));
|
||||
}
|
||||
|
||||
public function testIsValidMobilePhoneNumber()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('011-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('010-2345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('+82-11-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('82 010-2345-6789'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('010-1111-1111'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('02-345-6789'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('063-9876-5432'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('070-7654-3210'));
|
||||
}
|
||||
|
||||
public function testIsValidJuminNumber()
|
||||
{
|
||||
// These numbers are fake.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidJuminNumber('123456-3456787'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidJuminNumber('123456-3456788'));
|
||||
}
|
||||
|
||||
public function testIsValidCorporationNumber()
|
||||
{
|
||||
// These numbers are fake.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidCorporationNumber('123456-0123453'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidCorporationNumber('123456-0123454'));
|
||||
}
|
||||
|
||||
public function testIsValidBusinessNumber()
|
||||
{
|
||||
// These numbers are fake.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidBusinessNumber('123-45-67891'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidBusinessNumber('123-45-67892'));
|
||||
}
|
||||
|
||||
public function testIsKoreanIP()
|
||||
{
|
||||
// Private IP ranges.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('10.12.34.210'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('127.0.123.45'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('192.168.10.1'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('::1'));
|
||||
|
||||
// Korean IP ranges.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('115.71.233.0'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('114.207.12.3'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('2001:0320::1'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('2407:B800::F'));
|
||||
|
||||
// Foreign IP ranges.
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('216.58.197.0'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('170.14.168.0'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('2001:41d0:8:e8ad::1'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('2404:6800:4005:802::200e'));
|
||||
}
|
||||
|
||||
public function testIsKoreanEmailAddress()
|
||||
{
|
||||
// Test Korean portals.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@naver.com'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@hanmail.net'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@worksmobile.com'));
|
||||
|
||||
// Test foreign portals.
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@gmail.com'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@hotmail.com'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@yahoo.com'));
|
||||
|
||||
// Test third-party MX services.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@woorimail.com'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@rhymix.org'));
|
||||
}
|
||||
}
|
||||
22
tests/unit/framework/MIMETest.php
Normal file
22
tests/unit/framework/MIMETest.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
class MIMETest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testMIME()
|
||||
{
|
||||
$this->assertEquals('audio/ogg', Rhymix\Framework\MIME::getTypeByExtension('ogg'));
|
||||
$this->assertEquals('image/gif', Rhymix\Framework\MIME::getTypeByExtension('gif'));
|
||||
$this->assertEquals('text/html', Rhymix\Framework\MIME::getTypeByExtension('htm'));
|
||||
|
||||
$this->assertEquals('application/msword', Rhymix\Framework\MIME::getTypeByFilename('attachment.doc'));
|
||||
$this->assertEquals('application/pdf', Rhymix\Framework\MIME::getTypeByFilename('라이믹스.pdf'));
|
||||
$this->assertEquals('application/postscript', Rhymix\Framework\MIME::getTypeByFilename('MyGraphics.v2.eps'));
|
||||
$this->assertEquals('application/vnd.ms-excel', Mail::returnMIMEType('MySpreadsheet.xls'));
|
||||
$this->assertEquals('application/octet-stream', Mail::returnMIMEType('Untitled File'));
|
||||
|
||||
$this->assertEquals('odt', Rhymix\Framework\MIME::getExtensionByType('application/vnd.oasis.opendocument.text'));
|
||||
$this->assertEquals('jpg', Rhymix\Framework\MIME::getExtensionByType('image/jpeg'));
|
||||
$this->assertEquals('mpeg', Rhymix\Framework\MIME::getExtensionByType('video/mpeg'));
|
||||
$this->assertFalse(Rhymix\Framework\MIME::getExtensionByType('application/octet-stream'));
|
||||
}
|
||||
}
|
||||
48
tests/unit/framework/PaginationTest.php
Normal file
48
tests/unit/framework/PaginationTest.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
class PaginationTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testCountPages()
|
||||
{
|
||||
$this->assertEquals(1, Rhymix\Framework\Pagination::countPages(0, 20));
|
||||
$this->assertEquals(1, Rhymix\Framework\Pagination::countPages(10, 20));
|
||||
$this->assertEquals(1, Rhymix\Framework\Pagination::countPages(20, 20));
|
||||
$this->assertEquals(2, Rhymix\Framework\Pagination::countPages(21, 20));
|
||||
}
|
||||
|
||||
public function testCreateLinks()
|
||||
{
|
||||
$links = Rhymix\Framework\Pagination::createLinks('index.php?page=', 27, 3);
|
||||
$this->assertContains('<div class="pagination">', $links);
|
||||
$this->assertContains('<a href="index.php?page=3">', $links);
|
||||
$this->assertContains('<span class="page_number">1</span>', $links);
|
||||
$this->assertContains('<span class="page_number">10</span>', $links);
|
||||
|
||||
$links = Rhymix\Framework\Pagination::createLinks('/foo/bar/page/', 27, 13);
|
||||
$this->assertContains('<div class="pagination">', $links);
|
||||
$this->assertContains('<a href="/foo/bar/page/13">', $links);
|
||||
$this->assertContains('<span class="page_number">11</span>', $links);
|
||||
$this->assertContains('<span class="page_number">20</span>', $links);
|
||||
|
||||
$links = Rhymix\Framework\Pagination::createLinks('/rhymix?page=$PAGE&foo=bar', 27, 25);
|
||||
$this->assertContains('<div class="pagination">', $links);
|
||||
$this->assertContains('<a href="/rhymix?page=27&foo=bar">', $links);
|
||||
$this->assertContains('<span class="page_number">21</span>', $links);
|
||||
$this->assertContains('<span class="page_number">27</span>', $links);
|
||||
|
||||
$links = Rhymix\Framework\Pagination::createLinks('p', 27, 3, 10, Rhymix\Framework\Pagination::COUNT_STYLE_CONTINUOUS);
|
||||
$this->assertContains('<div class="pagination">', $links);
|
||||
$this->assertContains('<span class="page_number">1</span>', $links);
|
||||
$this->assertContains('<span class="page_number">10</span>', $links);
|
||||
|
||||
$links = Rhymix\Framework\Pagination::createLinks('p', 27, 13, 10, Rhymix\Framework\Pagination::COUNT_STYLE_CONTINUOUS);
|
||||
$this->assertContains('<div class="pagination">', $links);
|
||||
$this->assertContains('<span class="page_number">9</span>', $links);
|
||||
$this->assertContains('<span class="page_number">18</span>', $links);
|
||||
|
||||
$links = Rhymix\Framework\Pagination::createLinks('p', 27, 25, 10, Rhymix\Framework\Pagination::COUNT_STYLE_CONTINUOUS);
|
||||
$this->assertContains('<div class="pagination">', $links);
|
||||
$this->assertContains('<span class="page_number">18</span>', $links);
|
||||
$this->assertContains('<span class="page_number">27</span>', $links);
|
||||
}
|
||||
}
|
||||
260
tests/unit/framework/StorageTest.php
Normal file
260
tests/unit/framework/StorageTest.php
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
<?php
|
||||
|
||||
class StorageTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function _before()
|
||||
{
|
||||
Rhymix\Framework\Storage::deleteDirectory(\RX_BASEDIR . 'tests/_output', false);
|
||||
}
|
||||
|
||||
public function _after()
|
||||
{
|
||||
Rhymix\Framework\Storage::deleteDirectory(\RX_BASEDIR . 'tests/_output', false);
|
||||
}
|
||||
|
||||
public function _failed()
|
||||
{
|
||||
Rhymix\Framework\Storage::deleteDirectory(\RX_BASEDIR . 'tests/_output', false);
|
||||
}
|
||||
|
||||
public function testExists()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Storage::exists(__FILE__));
|
||||
$this->assertTrue(Rhymix\Framework\Storage::exists(__DIR__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::exists(__FILE__ . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::exists(__DIR__ . '/nonexistent.subdirectory'));
|
||||
}
|
||||
|
||||
public function testIsFile()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isFile(__FILE__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isFile(__DIR__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isFile(__FILE__ . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isFile(__DIR__ . '/nonexistent.subdirectory'));
|
||||
}
|
||||
|
||||
public function testIsEmptyFile()
|
||||
{
|
||||
$emptyfile = \RX_BASEDIR . 'tests/_output/emptyfile.txt';
|
||||
file_put_contents($emptyfile, '');
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isEmptyFile($emptyfile));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isEmptyFile($emptyfile . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isEmptyFile(__FILE__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isEmptyFile(__DIR__));
|
||||
}
|
||||
|
||||
public function testIsDirectory()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isDirectory(__DIR__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isDirectory(__FILE__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isDirectory(__FILE__ . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isDirectory(__DIR__ . '/nonexistent.subdirectory'));
|
||||
}
|
||||
|
||||
public function testIsEmptyDirectory()
|
||||
{
|
||||
$emptydir = \RX_BASEDIR . 'tests/_output/emptydir';
|
||||
mkdir($emptydir);
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isEmptyDirectory($emptydir));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isEmptyDirectory($emptydir . '/nonexistent.subdirectory'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isEmptyDirectory(__FILE__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isEmptyDirectory(__DIR__));
|
||||
}
|
||||
|
||||
public function testIsSymlink()
|
||||
{
|
||||
if (strncasecmp(\PHP_OS, 'Win', 3) === 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$symlink_source = \RX_BASEDIR . 'tests/_output/link.source.txt';
|
||||
$symlink_target = \RX_BASEDIR . 'tests/_output/link.target.txt';
|
||||
file_put_contents($symlink_target, 'foobar');
|
||||
symlink($symlink_target, $symlink_source);
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isSymlink($symlink_source));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isSymlink($symlink_target));
|
||||
unlink($symlink_target);
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isSymlink($symlink_source));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isValidSymlink($symlink_source));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isSymlink($symlink_target));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isValidSymlink($symlink_target));
|
||||
}
|
||||
|
||||
public function testIsReadable()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isReadable(__FILE__));
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isReadable(__DIR__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isReadable(__FILE__ . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isReadable('/dev/nonexistent'));
|
||||
}
|
||||
|
||||
public function testIsWritable()
|
||||
{
|
||||
$testfile = \RX_BASEDIR . 'tests/_output/testfile.txt';
|
||||
file_put_contents($testfile, 'foobar');
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isWritable(__FILE__));
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isWritable(__DIR__));
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isWritable($testfile));
|
||||
$this->assertTrue(Rhymix\Framework\Storage::isWritable(dirname($testfile)));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isWritable($testfile . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::isWritable('/dev/nonexistent'));
|
||||
}
|
||||
|
||||
public function testGetSize()
|
||||
{
|
||||
$this->assertEquals(filesize(__FILE__), Rhymix\Framework\Storage::getSize(__FILE__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::getSize(__DIR__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::getSize(__FILE__ . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::getSize('/dev/nonexistent'));
|
||||
}
|
||||
|
||||
public function testRead()
|
||||
{
|
||||
$this->assertEquals(file_get_contents(__FILE__), Rhymix\Framework\Storage::read(__FILE__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::read(__FILE__ . '.nonexistent.suffix'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::read(__DIR__));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::read('/dev/nonexistent'));
|
||||
}
|
||||
|
||||
public function testWrite()
|
||||
{
|
||||
$testfile = \RX_BASEDIR . 'tests/_output/subdirectory/testfile.txt';
|
||||
|
||||
$this->assertFalse(file_exists($testfile));
|
||||
$this->assertTrue(Rhymix\Framework\Storage::write($testfile, 'foobarbazzjazz'));
|
||||
$this->assertTrue(file_exists($testfile));
|
||||
$this->assertEquals('foobarbazzjazz', file_get_contents($testfile));
|
||||
}
|
||||
|
||||
public function testCopy()
|
||||
{
|
||||
$source = \RX_BASEDIR . 'tests/_output/copy.source.txt';
|
||||
$target = \RX_BASEDIR . 'tests/_output/copy.target.txt';
|
||||
file_put_contents($source, 'foobarbaz');
|
||||
chmod($source, 0646);
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::copy($source, $target));
|
||||
$this->assertTrue(file_exists($target));
|
||||
$this->assertTrue(file_get_contents($target) === 'foobarbaz');
|
||||
|
||||
if (strncasecmp(\PHP_OS, 'Win', 3) !== 0)
|
||||
{
|
||||
$this->assertEquals(0646, fileperms($target) & 0777);
|
||||
$this->assertTrue(Rhymix\Framework\Storage::copy($source, $target, 0755));
|
||||
$this->assertEquals(0755, fileperms($target) & 0777);
|
||||
}
|
||||
}
|
||||
|
||||
public function testMove()
|
||||
{
|
||||
$source = \RX_BASEDIR . 'tests/_output/move.source.txt';
|
||||
$target = \RX_BASEDIR . 'tests/_output/move.target.txt';
|
||||
file_put_contents($source, 'foobarbaz');
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::move($source, $target));
|
||||
$this->assertTrue(file_exists($target));
|
||||
$this->assertTrue(file_get_contents($target) === 'foobarbaz');
|
||||
$this->assertFalse(file_exists($source));
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
$testfile = \RX_BASEDIR . 'tests/_output/testfile.txt';
|
||||
file_put_contents($testfile, 'foobar');
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::delete($testfile));
|
||||
$this->assertFalse(file_exists($testfile));
|
||||
}
|
||||
|
||||
public function testCreateDirectory()
|
||||
{
|
||||
$emptydir = \RX_BASEDIR . 'tests/_output/emptydir';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::createDirectory($emptydir));
|
||||
$this->assertTrue(file_exists($emptydir) && is_dir($emptydir));
|
||||
}
|
||||
|
||||
public function testReadDirectory()
|
||||
{
|
||||
$testdir = \RX_BASEDIR . 'tests/_output/testdir';
|
||||
mkdir($testdir);
|
||||
mkdir($testdir . '/subdir');
|
||||
file_put_contents($testdir . '/.dotfile', '');
|
||||
file_put_contents($testdir . '/foo', 'foo');
|
||||
file_put_contents($testdir . '/bar', 'bar');
|
||||
file_put_contents($testdir . '/baz', 'baz');
|
||||
|
||||
$this->assertEquals(array($testdir . '/bar', $testdir . '/baz', $testdir . '/foo'), Rhymix\Framework\Storage::readDirectory($testdir));
|
||||
$this->assertEquals(array('bar', 'baz', 'foo'), Rhymix\Framework\Storage::readDirectory($testdir, false));
|
||||
$this->assertEquals(array('bar', 'baz', 'foo', 'subdir'), Rhymix\Framework\Storage::readDirectory($testdir, false, true, false));
|
||||
$this->assertEquals(array('.dotfile', 'bar', 'baz', 'foo'), Rhymix\Framework\Storage::readDirectory($testdir, false, false, true));
|
||||
$this->assertEquals(array('.dotfile', 'bar', 'baz', 'foo', 'subdir'), Rhymix\Framework\Storage::readDirectory($testdir, false, false, false));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::readDirectory('/opt/nonexistent.foobar'));
|
||||
}
|
||||
|
||||
public function testCopyDirectory()
|
||||
{
|
||||
$sourcedir = \RX_BASEDIR . 'tests/_output/sourcedir';
|
||||
mkdir($sourcedir);
|
||||
mkdir($sourcedir . '/subdir');
|
||||
file_put_contents($sourcedir . '/bar', 'bar');
|
||||
file_put_contents($sourcedir . '/subdir/baz', 'baz');
|
||||
$targetdir = \RX_BASEDIR . 'tests/_output/targetdir';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::copyDirectory($sourcedir, $targetdir));
|
||||
$this->assertTrue(file_exists($targetdir . '/bar'));
|
||||
$this->assertTrue(file_exists($targetdir . '/subdir/baz'));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::copyDirectory($sourcedir, '/opt/nonexistent.foobar'));
|
||||
}
|
||||
|
||||
public function testMoveDirectory()
|
||||
{
|
||||
$sourcedir = \RX_BASEDIR . 'tests/_output/sourcedir';
|
||||
mkdir($sourcedir);
|
||||
mkdir($sourcedir . '/subdir');
|
||||
file_put_contents($sourcedir . '/bar', 'bar');
|
||||
file_put_contents($sourcedir . '/subdir/baz', 'baz');
|
||||
$targetdir = \RX_BASEDIR . 'tests/_output/targetdir';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::moveDirectory($sourcedir, $targetdir));
|
||||
$this->assertTrue(file_exists($targetdir . '/bar'));
|
||||
$this->assertTrue(file_exists($targetdir . '/subdir/baz'));
|
||||
$this->assertFalse(file_exists($sourcedir));
|
||||
}
|
||||
|
||||
public function testDeleteDirectory()
|
||||
{
|
||||
$sourcedir = \RX_BASEDIR . 'tests/_output/sourcedir';
|
||||
mkdir($sourcedir);
|
||||
mkdir($sourcedir . '/subdir');
|
||||
file_put_contents($sourcedir . '/bar', 'bar');
|
||||
file_put_contents($sourcedir . '/subdir/baz', 'baz');
|
||||
$nonexistent = \RX_BASEDIR . 'tests/_output/targetdir';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::deleteDirectory($sourcedir));
|
||||
$this->assertFalse(file_exists($sourcedir . '/subdir/baz'));
|
||||
$this->assertFalse(file_exists($sourcedir));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::deleteDirectory($nonexistent));
|
||||
}
|
||||
|
||||
public function testDeleteDirectoryKeepRoot()
|
||||
{
|
||||
$sourcedir = \RX_BASEDIR . 'tests/_output/sourcedir';
|
||||
mkdir($sourcedir);
|
||||
mkdir($sourcedir . '/subdir');
|
||||
file_put_contents($sourcedir . '/bar', 'bar');
|
||||
file_put_contents($sourcedir . '/subdir/baz', 'baz');
|
||||
$nonexistent = \RX_BASEDIR . 'tests/_output/targetdir';
|
||||
|
||||
$this->assertTrue(Rhymix\Framework\Storage::deleteDirectory($sourcedir, false));
|
||||
$this->assertFalse(file_exists($sourcedir . '/subdir/baz'));
|
||||
$this->assertTrue(file_exists($sourcedir));
|
||||
$this->assertFalse(Rhymix\Framework\Storage::deleteDirectory($nonexistent));
|
||||
}
|
||||
}
|
||||
71
tests/unit/framework/TimerTest.php
Normal file
71
tests/unit/framework/TimerTest.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
class TimerTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
function testStartStop()
|
||||
{
|
||||
$t1 = microtime(true);
|
||||
usleep(1000);
|
||||
$started = Rhymix\Framework\Timer::start();
|
||||
usleep(1000);
|
||||
$t2 = microtime(true);
|
||||
usleep(1000);
|
||||
$elapsed = Rhymix\Framework\Timer::stop();
|
||||
usleep(1000);
|
||||
$t3 = microtime(true);
|
||||
|
||||
$this->assertGreaterThanOrEqual($t1, $started);
|
||||
$this->assertLessThanOrEqual($t2, $started);
|
||||
$this->assertGreaterThanOrEqual($t2 - $started, $elapsed);
|
||||
$this->assertLessThanOrEqual($t3 - $t1, $elapsed);
|
||||
$this->assertGreaterThan(0, $elapsed);
|
||||
}
|
||||
|
||||
function testNestedTimers()
|
||||
{
|
||||
$t1 = Rhymix\Framework\Timer::start();
|
||||
usleep(1000);
|
||||
$t2 = Rhymix\Framework\Timer::start();
|
||||
usleep(1000);
|
||||
$t3 = Rhymix\Framework\Timer::stop();
|
||||
usleep(1000);
|
||||
$t4 = Rhymix\Framework\Timer::stop();
|
||||
|
||||
$this->assertGreaterThanOrEqual($t1, $t2);
|
||||
$this->assertGreaterThan($t3, $t4);
|
||||
}
|
||||
|
||||
function testMultipleTimers()
|
||||
{
|
||||
$t1 = Rhymix\Framework\Timer::start('timer1');
|
||||
usleep(5000);
|
||||
$t2 = Rhymix\Framework\Timer::start('timer2');
|
||||
usleep(1000);
|
||||
$t3 = Rhymix\Framework\Timer::stop('timer1');
|
||||
usleep(2000);
|
||||
$t4 = Rhymix\Framework\Timer::stop('timer2');
|
||||
|
||||
$this->assertGreaterThanOrEqual($t1, $t2);
|
||||
$this->assertGreaterThanOrEqual($t4, $t3);
|
||||
}
|
||||
|
||||
function testTimerFormat()
|
||||
{
|
||||
$t1 = Rhymix\Framework\Timer::start();
|
||||
usleep(1000);
|
||||
$t2 = Rhymix\Framework\Timer::stopFormat();
|
||||
|
||||
$this->assertRegexp('/^[0-9\.,]+ms$/', $t2);
|
||||
}
|
||||
|
||||
function testTimerSinceStartup()
|
||||
{
|
||||
$t1 = Rhymix\Framework\Timer::sinceStartup();
|
||||
$t2 = Rhymix\Framework\Timer::sinceStartup();
|
||||
|
||||
$this->assertGreaterThanOrEqual($t1, $t2);
|
||||
|
||||
$t3 = Rhymix\Framework\Timer::sinceStartupFormat();
|
||||
$this->assertRegexp('/^[0-9\.,]+ms$/', $t3);
|
||||
}
|
||||
}
|
||||
104
tests/unit/framework/UATest.php
Normal file
104
tests/unit/framework/UATest.php
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
class UATest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testIsMobile()
|
||||
{
|
||||
// Phones
|
||||
$this->assertTrue(Rhymix\Framework\UA::isMobile('Mozilla/5.0 (Linux; Android 5.0; Nexus 5 Build/LPX13D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.102 Mobile Safari/537.36'));
|
||||
$this->assertTrue(Rhymix\Framework\UA::isMobile('Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'));
|
||||
|
||||
// Tablets
|
||||
$this->assertTrue(Rhymix\Framework\UA::isMobile('Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'));
|
||||
$this->assertTrue(Rhymix\Framework\UA::isMobile('Mozilla/5.0 (Linux; Android 4.4.2; SM-T530 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Safari/537.36'));
|
||||
|
||||
// Not mobile
|
||||
$this->assertFalse(Rhymix\Framework\UA::isMobile('Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'));
|
||||
$this->assertFalse(Rhymix\Framework\UA::isMobile('Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36'));
|
||||
$this->assertFalse(Rhymix\Framework\UA::isMobile('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0'));
|
||||
$this->assertFalse(Rhymix\Framework\UA::isMobile('Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16'));
|
||||
}
|
||||
|
||||
public function testIsTablet()
|
||||
{
|
||||
// Phones
|
||||
$this->assertFalse(Rhymix\Framework\UA::isTablet('Mozilla/5.0 (Linux; Android 5.0; Nexus 5 Build/LPX13D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.102 Mobile Safari/537.36'));
|
||||
$this->assertFalse(Rhymix\Framework\UA::isTablet('Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'));
|
||||
|
||||
// Tablets
|
||||
$this->assertTrue(Rhymix\Framework\UA::isTablet('Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'));
|
||||
$this->assertTrue(Rhymix\Framework\UA::isTablet('Mozilla/5.0 (Linux; Android 4.4.2; SM-T530 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Safari/537.36'));
|
||||
|
||||
// Not mobile
|
||||
$this->assertFalse(Rhymix\Framework\UA::isTablet('Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'));
|
||||
$this->assertFalse(Rhymix\Framework\UA::isTablet('Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'));
|
||||
}
|
||||
|
||||
public function testIsRobot()
|
||||
{
|
||||
// Robot
|
||||
$this->assertTrue(Rhymix\Framework\UA::isRobot('Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)'));
|
||||
$this->assertTrue(Rhymix\Framework\UA::isRobot('Googlebot/2.1 (+http://www.googlebot.com/bot.html)'));
|
||||
$this->assertTrue(Rhymix\Framework\UA::isRobot('Yeti/1.0 (NHN Corp.; http://help.naver.com/robots/)'));
|
||||
|
||||
// Not robot
|
||||
$this->assertFalse(Rhymix\Framework\UA::isRobot('Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'));
|
||||
$this->assertFalse(Rhymix\Framework\UA::isRobot('Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'));
|
||||
$this->assertFalse(Rhymix\Framework\UA::isRobot('Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'));
|
||||
}
|
||||
|
||||
public function testGetBrowserInfo()
|
||||
{
|
||||
// Android default browser
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/5.0 (Linux; U; Android 4.0.3; Device Name) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30');
|
||||
$this->assertEquals('Android', $browser->browser);
|
||||
$this->assertEquals('4.0', $browser->version);
|
||||
$this->assertEquals('Android', $browser->os);
|
||||
$this->assertTrue($browser->is_mobile);
|
||||
$this->assertTrue($browser->is_tablet);
|
||||
|
||||
// Mobile Chrome
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/5.0 (Linux; Android 5.0; Nexus 5 Build/LPX13D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.102 Mobile Safari/537.36');
|
||||
$this->assertEquals('Chrome', $browser->browser);
|
||||
$this->assertEquals('38.0', $browser->version);
|
||||
$this->assertEquals('Android', $browser->os);
|
||||
$this->assertTrue($browser->is_mobile);
|
||||
$this->assertFalse($browser->is_tablet);
|
||||
|
||||
// Edge
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136');
|
||||
$this->assertEquals('Edge', $browser->browser);
|
||||
$this->assertEquals('12.0', $browser->version);
|
||||
$this->assertEquals('Windows', $browser->os);
|
||||
$this->assertFalse($browser->is_mobile);
|
||||
$this->assertFalse($browser->is_tablet);
|
||||
|
||||
// IE 11
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko');
|
||||
$this->assertEquals('IE', $browser->browser);
|
||||
$this->assertEquals('11.0', $browser->version);
|
||||
$this->assertEquals('Windows', $browser->os);
|
||||
|
||||
// IE 10 in compatibility mode
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/4.0 (Compatible; MSIE 8.0; Windows NT 5.2; Trident/6.0)');
|
||||
$this->assertEquals('IE', $browser->browser);
|
||||
$this->assertEquals('10.0', $browser->version);
|
||||
|
||||
// IE 8 in compatibility mode
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)');
|
||||
$this->assertEquals('IE', $browser->browser);
|
||||
$this->assertEquals('8.0', $browser->version);
|
||||
|
||||
// Linux Chrome
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36');
|
||||
$this->assertEquals('Chrome', $browser->browser);
|
||||
$this->assertEquals('41.0', $browser->version);
|
||||
$this->assertEquals('Linux', $browser->os);
|
||||
|
||||
// OS X Firefox
|
||||
$browser = Rhymix\Framework\UA::getBrowserInfo('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0');
|
||||
$this->assertEquals('Firefox', $browser->browser);
|
||||
$this->assertEquals('33.0', $browser->version);
|
||||
$this->assertEquals('OS X', $browser->os);
|
||||
}
|
||||
}
|
||||
41
tests/unit/framework/i18nTest.php
Normal file
41
tests/unit/framework/i18nTest.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
class i18nTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testListCountries()
|
||||
{
|
||||
$sort_code_2 = Rhymix\Framework\i18n::listCountries(Rhymix\Framework\i18n::SORT_CODE_2);
|
||||
$this->assertEquals('AD', array_first($sort_code_2)->iso_3166_1_alpha2);
|
||||
$this->assertEquals('AND', array_first_key($sort_code_2));
|
||||
|
||||
$sort_code_3 = Rhymix\Framework\i18n::listCountries(Rhymix\Framework\i18n::SORT_CODE_3);
|
||||
$this->assertEquals('ABW', array_first($sort_code_3)->iso_3166_1_alpha3);
|
||||
$this->assertEquals('ABW', array_first_key($sort_code_3));
|
||||
|
||||
$sort_code_n = Rhymix\Framework\i18n::listCountries(Rhymix\Framework\i18n::SORT_CODE_NUMERIC);
|
||||
$this->assertEquals('004', array_first($sort_code_n)->iso_3166_1_numeric);
|
||||
$this->assertEquals('AFG', array_first_key($sort_code_n));
|
||||
|
||||
$sort_cctld = Rhymix\Framework\i18n::listCountries(Rhymix\Framework\i18n::SORT_CCTLD);
|
||||
$this->assertEquals('zw', array_last($sort_cctld)->cctld);
|
||||
$this->assertEquals('ZWE', array_last_key($sort_cctld));
|
||||
|
||||
$sort_english = Rhymix\Framework\i18n::listCountries(Rhymix\Framework\i18n::SORT_NAME_ENGLISH);
|
||||
$this->assertEquals('Afghanistan', array_first($sort_english)->name_english);
|
||||
$this->assertEquals('AFG', array_first_key($sort_english));
|
||||
$this->assertEquals('Åland Islands', array_last($sort_english)->name_english);
|
||||
$this->assertEquals('ALA', array_last_key($sort_english));
|
||||
|
||||
$sort_korean = Rhymix\Framework\i18n::listCountries(Rhymix\Framework\i18n::SORT_NAME_KOREAN);
|
||||
$this->assertEquals('가나', array_first($sort_korean)->name_korean);
|
||||
$this->assertEquals('GHA', array_first_key($sort_korean));
|
||||
$this->assertEquals('홍콩', array_last($sort_korean)->name_korean);
|
||||
$this->assertEquals('HKG', array_last_key($sort_korean));
|
||||
|
||||
$sort_native = Rhymix\Framework\i18n::listCountries(Rhymix\Framework\i18n::SORT_NAME_NATIVE);
|
||||
$this->assertEquals('Amerika Sāmoa', array_first($sort_native)->name_native);
|
||||
$this->assertEquals('대한민국', $sort_native['KOR']->name_korean);
|
||||
$this->assertEquals('United States of America', $sort_native['USA']->name_english);
|
||||
$this->assertEquals('nz', $sort_native['NZL']->cctld);
|
||||
}
|
||||
}
|
||||
89
tools/korea_ip_ranges/korea.ipv4.parser.php
Normal file
89
tools/korea_ip_ranges/korea.ipv4.parser.php
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Do not allow execution over the web.
|
||||
*/
|
||||
if (PHP_SAPI !== 'cli')
|
||||
{
|
||||
exit 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the latest IPv4 data from libkrisp.
|
||||
*/
|
||||
$download_url = 'https://mirror.oops.org/pub/oops/libkrisp/data/v2/krisp.csv.gz';
|
||||
$referer_url = 'https://mirror.oops.org/pub/oops/libkrisp/data/v2/';
|
||||
$content = file_get_contents($download_url, false, stream_context_create(array(
|
||||
'http' => array(
|
||||
'user_agent' => 'Mozilla/5.0 (compatible; IP range generator)',
|
||||
'header' => 'Referer: ' . $referer_url . "\r\n",
|
||||
),
|
||||
)));
|
||||
$content = gzdecode($content);
|
||||
if (!$content)
|
||||
{
|
||||
exit 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load IP range data.
|
||||
*/
|
||||
$ranges = array();
|
||||
$content = explode("\n", $content);
|
||||
foreach ($content as $line)
|
||||
{
|
||||
$line = explode("\t", $line);
|
||||
if (count($line) < 2) continue;
|
||||
$start = trim($line[0]);
|
||||
$end = trim($line[1]);
|
||||
$ranges[$start] = array($start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the ranges.
|
||||
*/
|
||||
ksort($ranges);
|
||||
$ranges = array_values($ranges);
|
||||
$count = count($ranges);
|
||||
|
||||
/**
|
||||
* Merge adjacent ranges.
|
||||
*/
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
if ($i == 0) continue;
|
||||
$previous_i = $i - 1;
|
||||
while (true)
|
||||
{
|
||||
if ($ranges[$previous_i] !== null) break;
|
||||
$previous_i--;
|
||||
}
|
||||
|
||||
if ($ranges[$i][0] == $ranges[$previous_i][1] + 1)
|
||||
{
|
||||
$ranges[$previous_i][1] = $ranges[$i][1];
|
||||
$ranges[$i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize into final format.
|
||||
*/
|
||||
$ranges_final = array();
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if ($range !== null) $ranges_final[] = $range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save to file.
|
||||
*/
|
||||
$content = '<' . '?php' . "\n\n" . '/**' . "\n" . ' * Source: ' . $referer_url . "\n";
|
||||
$content .= ' * Last Updated: ' . date('Y-m-d') . "\n" . ' */' . "\n";
|
||||
$content .= 'return ' . var_export($ranges_final, true) . ';' . "\n";
|
||||
file_put_contents('korea.ipv4.php', $content);
|
||||
|
||||
/**
|
||||
* Report status.
|
||||
*/
|
||||
echo count($ranges_final) . ' IPv4 ranges saved.' . PHP_EOL;
|
||||
92
tools/korea_ip_ranges/korea.ipv6.parser.php
Normal file
92
tools/korea_ip_ranges/korea.ipv6.parser.php
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Do not allow execution over the web.
|
||||
*/
|
||||
if (PHP_SAPI !== 'cli')
|
||||
{
|
||||
exit 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the latest IPv6 data from KISA.
|
||||
*/
|
||||
$download_url = 'https://ip.kisa.or.kr/ip_cate_stat/stat_05_05_toexcel.act';
|
||||
$referer_url = 'https://ip.kisa.or.kr/ip_cate_stat/stat_05_05.act';
|
||||
$content = file_get_contents($download_url, false, stream_context_create(array(
|
||||
'http' => array(
|
||||
'user_agent' => 'Mozilla/5.0 (compatible; IP range generator)',
|
||||
'header' => 'Referer: ' . $referer_url . "\r\n",
|
||||
),
|
||||
)));
|
||||
if (!$content)
|
||||
{
|
||||
exit 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the HTML/Excel document.
|
||||
*/
|
||||
$regex = '#<tr>\\s*<td [^>]+>([0-9a-f:]+::)</td>\\s*<td [^>]+>(/[0-9]+)</td>#iU';
|
||||
preg_match_all($regex, $content, $matches, PREG_SET_ORDER);
|
||||
|
||||
/**
|
||||
* Extract the address and netmask for each range.
|
||||
*/
|
||||
$ranges = array();
|
||||
foreach ($matches as $match)
|
||||
{
|
||||
$start = str_pad(str_replace(':', '', strtolower($match[1])), 16, '0', STR_PAD_RIGHT);
|
||||
$mask = str_repeat('f', ((64 - trim($match[2], '/')) / 4));
|
||||
$end = substr($start, 0, 16 - strlen($mask)) . $mask;
|
||||
$ranges[$start] = array($start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the ranges.
|
||||
*/
|
||||
ksort($ranges);
|
||||
$ranges = array_values($ranges);
|
||||
$count = count($ranges);
|
||||
|
||||
/**
|
||||
* Merge adjacent ranges.
|
||||
*/
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
if ($i == 0) continue;
|
||||
$previous_i = $i - 1;
|
||||
while (true)
|
||||
{
|
||||
if ($ranges[$previous_i] !== null) break;
|
||||
$previous_i--;
|
||||
}
|
||||
|
||||
if (hexdec($ranges[$i][0]) == hexdec($ranges[$previous_i][1]) + 1)
|
||||
{
|
||||
$ranges[$previous_i][1] = $ranges[$i][1];
|
||||
$ranges[$i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize into final format.
|
||||
*/
|
||||
$ranges_final = array();
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if ($range !== null) $ranges_final[] = $range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save to file.
|
||||
*/
|
||||
$content = '<' . '?php' . "\n\n" . '/**' . "\n" . ' * Source: ' . $referer_url . "\n";
|
||||
$content .= ' * Last Updated: ' . date('Y-m-d') . "\n" . ' */' . "\n";
|
||||
$content .= 'return ' . var_export($ranges_final, true) . ';' . "\n";
|
||||
file_put_contents('korea.ipv6.php', $content);
|
||||
|
||||
/**
|
||||
* Report status.
|
||||
*/
|
||||
echo count($ranges_final) . ' IPv6 ranges saved.' . PHP_EOL;
|
||||
1
vendor/bin/html-to-markdown
vendored
Symbolic link
1
vendor/bin/html-to-markdown
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../league/html-to-markdown/bin/html-to-markdown
|
||||
1
vendor/bin/pscss
vendored
Symbolic link
1
vendor/bin/pscss
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../leafo/scssphp/bin/pscss
|
||||
73
vendor/composer/autoload_classmap.php
vendored
73
vendor/composer/autoload_classmap.php
vendored
|
|
@ -238,6 +238,67 @@ return array(
|
|||
'HTMLPurifier_VarParser_Native' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php',
|
||||
'HTMLPurifier_Zipper' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php',
|
||||
'Hautelook\\Phpass\\PasswordHash' => $vendorDir . '/hautelook/phpass/src/Hautelook/Phpass/PasswordHash.php',
|
||||
'JBBCode\\CodeDefinition' => $vendorDir . '/jbbcode/jbbcode/JBBCode/CodeDefinition.php',
|
||||
'JBBCode\\CodeDefinitionBuilder' => $vendorDir . '/jbbcode/jbbcode/JBBCode/CodeDefinitionBuilder.php',
|
||||
'JBBCode\\CodeDefinitionSet' => $vendorDir . '/jbbcode/jbbcode/JBBCode/CodeDefinitionSet.php',
|
||||
'JBBCode\\DefaultCodeDefinitionSet' => $vendorDir . '/jbbcode/jbbcode/JBBCode/DefaultCodeDefinitionSet.php',
|
||||
'JBBCode\\DocumentElement' => $vendorDir . '/jbbcode/jbbcode/JBBCode/DocumentElement.php',
|
||||
'JBBCode\\ElementNode' => $vendorDir . '/jbbcode/jbbcode/JBBCode/ElementNode.php',
|
||||
'JBBCode\\InputValidator' => $vendorDir . '/jbbcode/jbbcode/JBBCode/InputValidator.php',
|
||||
'JBBCode\\Node' => $vendorDir . '/jbbcode/jbbcode/JBBCode/Node.php',
|
||||
'JBBCode\\NodeVisitor' => $vendorDir . '/jbbcode/jbbcode/JBBCode/NodeVisitor.php',
|
||||
'JBBCode\\Parser' => $vendorDir . '/jbbcode/jbbcode/JBBCode/Parser.php',
|
||||
'JBBCode\\ParserException' => $vendorDir . '/jbbcode/jbbcode/JBBCode/ParserException.php',
|
||||
'JBBCode\\TextNode' => $vendorDir . '/jbbcode/jbbcode/JBBCode/TextNode.php',
|
||||
'JBBCode\\Tokenizer' => $vendorDir . '/jbbcode/jbbcode/JBBCode/Tokenizer.php',
|
||||
'JBBCode\\validators\\CssColorValidator' => $vendorDir . '/jbbcode/jbbcode/JBBCode/validators/CssColorValidator.php',
|
||||
'JBBCode\\validators\\UrlValidator' => $vendorDir . '/jbbcode/jbbcode/JBBCode/validators/UrlValidator.php',
|
||||
'JBBCode\\visitors\\HTMLSafeVisitor' => $vendorDir . '/jbbcode/jbbcode/JBBCode/visitors/HTMLSafeVisitor.php',
|
||||
'JBBCode\\visitors\\NestLimitVisitor' => $vendorDir . '/jbbcode/jbbcode/JBBCode/visitors/NestLimitVisitor.php',
|
||||
'JBBCode\\visitors\\SmileyVisitor' => $vendorDir . '/jbbcode/jbbcode/JBBCode/visitors/SmileyVisitor.php',
|
||||
'JBBCode\\visitors\\TagCountingVisitor' => $vendorDir . '/jbbcode/jbbcode/JBBCode/visitors/TagCountingVisitor.php',
|
||||
'Leafo\\ScssPhp\\Base\\Range' => $vendorDir . '/leafo/scssphp/src/Base/Range.php',
|
||||
'Leafo\\ScssPhp\\Block' => $vendorDir . '/leafo/scssphp/src/Block.php',
|
||||
'Leafo\\ScssPhp\\Colors' => $vendorDir . '/leafo/scssphp/src/Colors.php',
|
||||
'Leafo\\ScssPhp\\Compiler' => $vendorDir . '/leafo/scssphp/src/Compiler.php',
|
||||
'Leafo\\ScssPhp\\Compiler\\Environment' => $vendorDir . '/leafo/scssphp/src/Compiler/Environment.php',
|
||||
'Leafo\\ScssPhp\\Formatter' => $vendorDir . '/leafo/scssphp/src/Formatter.php',
|
||||
'Leafo\\ScssPhp\\Formatter\\Compact' => $vendorDir . '/leafo/scssphp/src/Formatter/Compact.php',
|
||||
'Leafo\\ScssPhp\\Formatter\\Compressed' => $vendorDir . '/leafo/scssphp/src/Formatter/Compressed.php',
|
||||
'Leafo\\ScssPhp\\Formatter\\Crunched' => $vendorDir . '/leafo/scssphp/src/Formatter/Crunched.php',
|
||||
'Leafo\\ScssPhp\\Formatter\\Debug' => $vendorDir . '/leafo/scssphp/src/Formatter/Debug.php',
|
||||
'Leafo\\ScssPhp\\Formatter\\Expanded' => $vendorDir . '/leafo/scssphp/src/Formatter/Expanded.php',
|
||||
'Leafo\\ScssPhp\\Formatter\\Nested' => $vendorDir . '/leafo/scssphp/src/Formatter/Nested.php',
|
||||
'Leafo\\ScssPhp\\Formatter\\OutputBlock' => $vendorDir . '/leafo/scssphp/src/Formatter/OutputBlock.php',
|
||||
'Leafo\\ScssPhp\\Node' => $vendorDir . '/leafo/scssphp/src/Node.php',
|
||||
'Leafo\\ScssPhp\\Node\\Number' => $vendorDir . '/leafo/scssphp/src/Node/Number.php',
|
||||
'Leafo\\ScssPhp\\Parser' => $vendorDir . '/leafo/scssphp/src/Parser.php',
|
||||
'Leafo\\ScssPhp\\Server' => $vendorDir . '/leafo/scssphp/src/Server.php',
|
||||
'Leafo\\ScssPhp\\Type' => $vendorDir . '/leafo/scssphp/src/Type.php',
|
||||
'Leafo\\ScssPhp\\Util' => $vendorDir . '/leafo/scssphp/src/Util.php',
|
||||
'Leafo\\ScssPhp\\Version' => $vendorDir . '/leafo/scssphp/src/Version.php',
|
||||
'League\\HTMLToMarkdown\\Configuration' => $vendorDir . '/league/html-to-markdown/src/Configuration.php',
|
||||
'League\\HTMLToMarkdown\\ConfigurationAwareInterface' => $vendorDir . '/league/html-to-markdown/src/ConfigurationAwareInterface.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\BlockquoteConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/BlockquoteConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\CommentConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/CommentConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\ConverterInterface' => $vendorDir . '/league/html-to-markdown/src/Converter/ConverterInterface.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\DefaultConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/DefaultConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\DivConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/DivConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\EmphasisConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/EmphasisConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\HardBreakConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/HardBreakConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\HeaderConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/HeaderConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\HorizontalRuleConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/HorizontalRuleConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\ImageConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ImageConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\LinkConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/LinkConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\ListBlockConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ListBlockConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\ListItemConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ListItemConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\ParagraphConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ParagraphConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\PreformattedConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/PreformattedConverter.php',
|
||||
'League\\HTMLToMarkdown\\Converter\\TextConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/TextConverter.php',
|
||||
'League\\HTMLToMarkdown\\Element' => $vendorDir . '/league/html-to-markdown/src/Element.php',
|
||||
'League\\HTMLToMarkdown\\ElementInterface' => $vendorDir . '/league/html-to-markdown/src/ElementInterface.php',
|
||||
'League\\HTMLToMarkdown\\Environment' => $vendorDir . '/league/html-to-markdown/src/Environment.php',
|
||||
'League\\HTMLToMarkdown\\HtmlConverter' => $vendorDir . '/league/html-to-markdown/src/HtmlConverter.php',
|
||||
'MatthiasMullie\\Minify\\CSS' => $vendorDir . '/matthiasmullie/minify/src/CSS.php',
|
||||
'MatthiasMullie\\Minify\\Exception' => $vendorDir . '/matthiasmullie/minify/src/Exception.php',
|
||||
'MatthiasMullie\\Minify\\Exceptions\\BasicException' => $vendorDir . '/matthiasmullie/minify/src/Exceptions/BasicException.php',
|
||||
|
|
@ -304,4 +365,16 @@ return array(
|
|||
'Requests_Utility_FilteredIterator' => $vendorDir . '/rmccue/requests/library/Requests/Utility/FilteredIterator.php',
|
||||
'Sunra\\PhpSimple\\HtmlDomParser' => $vendorDir . '/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/HtmlDomParser.php',
|
||||
'TrueBV\\Punycode' => $vendorDir . '/true/punycode/src/Punycode.php',
|
||||
'lessc' => $vendorDir . '/leafo/lessphp/lessc.inc.php',
|
||||
'lessc_formatter_classic' => $vendorDir . '/leafo/lessphp/lessc.inc.php',
|
||||
'lessc_formatter_compressed' => $vendorDir . '/leafo/lessphp/lessc.inc.php',
|
||||
'lessc_formatter_lessjs' => $vendorDir . '/leafo/lessphp/lessc.inc.php',
|
||||
'lessc_parser' => $vendorDir . '/leafo/lessphp/lessc.inc.php',
|
||||
'scss_formatter' => $vendorDir . '/leafo/scssphp/classmap.php',
|
||||
'scss_formatter_compressed' => $vendorDir . '/leafo/scssphp/classmap.php',
|
||||
'scss_formatter_crunched' => $vendorDir . '/leafo/scssphp/classmap.php',
|
||||
'scss_formatter_nested' => $vendorDir . '/leafo/scssphp/classmap.php',
|
||||
'scss_parser' => $vendorDir . '/leafo/scssphp/classmap.php',
|
||||
'scss_server' => $vendorDir . '/leafo/scssphp/classmap.php',
|
||||
'scssc' => $vendorDir . '/leafo/scssphp/classmap.php',
|
||||
);
|
||||
|
|
|
|||
3
vendor/composer/autoload_namespaces.php
vendored
3
vendor/composer/autoload_namespaces.php
vendored
|
|
@ -8,7 +8,8 @@ $baseDir = dirname($vendorDir);
|
|||
return array(
|
||||
'Sunra\\PhpSimple\\HtmlDomParser' => array($vendorDir . '/sunra/php-simple-html-dom-parser/Src'),
|
||||
'Requests' => array($vendorDir . '/rmccue/requests/library'),
|
||||
'Michelf' => array($vendorDir . '/michelf/php-markdown'),
|
||||
'Michelf' => array($vendorDir . '/michelf/php-markdown', $vendorDir . '/michelf/php-smartypants'),
|
||||
'JBBCode' => array($vendorDir . '/jbbcode/jbbcode'),
|
||||
'Hautelook' => array($vendorDir . '/hautelook/phpass/src'),
|
||||
'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'),
|
||||
);
|
||||
|
|
|
|||
2
vendor/composer/autoload_psr4.php
vendored
2
vendor/composer/autoload_psr4.php
vendored
|
|
@ -9,4 +9,6 @@ return array(
|
|||
'TrueBV\\' => array($vendorDir . '/true/punycode/src'),
|
||||
'MatthiasMullie\\PathConverter\\' => array($vendorDir . '/matthiasmullie/path-converter/src'),
|
||||
'MatthiasMullie\\Minify\\' => array($vendorDir . '/matthiasmullie/minify/src'),
|
||||
'League\\HTMLToMarkdown\\' => array($vendorDir . '/league/html-to-markdown/src'),
|
||||
'Leafo\\ScssPhp\\' => array($vendorDir . '/leafo/scssphp/src'),
|
||||
);
|
||||
|
|
|
|||
378
vendor/composer/installed.json
vendored
378
vendor/composer/installed.json
vendored
|
|
@ -92,59 +92,6 @@
|
|||
"html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "michelf/php-markdown",
|
||||
"version": "1.5.0",
|
||||
"version_normalized": "1.5.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/michelf/php-markdown.git",
|
||||
"reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/e1aabe18173231ebcefc90e615565742fc1c7fd9",
|
||||
"reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2015-03-01 12:03:08",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-lib": "1.4.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Michelf": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "John Gruber",
|
||||
"homepage": "http://daringfireball.net/"
|
||||
},
|
||||
{
|
||||
"name": "Michel Fortin",
|
||||
"email": "michel.fortin@michelf.ca",
|
||||
"homepage": "https://michelf.ca/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "PHP Markdown",
|
||||
"homepage": "https://michelf.ca/projects/php-markdown/",
|
||||
"keywords": [
|
||||
"markdown"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sunra/php-simple-html-dom-parser",
|
||||
"version": "v1.5.0",
|
||||
|
|
@ -537,5 +484,330 @@
|
|||
"password",
|
||||
"security"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "michelf/php-markdown",
|
||||
"version": "1.6.0",
|
||||
"version_normalized": "1.6.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/michelf/php-markdown.git",
|
||||
"reference": "156e56ee036505ec637d761ee62dc425d807183c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c",
|
||||
"reference": "156e56ee036505ec637d761ee62dc425d807183c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2015-12-24 01:37:31",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-lib": "1.4.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Michelf": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michel Fortin",
|
||||
"email": "michel.fortin@michelf.ca",
|
||||
"homepage": "https://michelf.ca/",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "John Gruber",
|
||||
"homepage": "https://daringfireball.net/"
|
||||
}
|
||||
],
|
||||
"description": "PHP Markdown",
|
||||
"homepage": "https://michelf.ca/projects/php-markdown/",
|
||||
"keywords": [
|
||||
"markdown"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "jbbcode/jbbcode",
|
||||
"version": "v1.3.0",
|
||||
"version_normalized": "1.3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jbowens/jBBCode.git",
|
||||
"reference": "645b6a1c0afa92b7d029d3417ebd8b60a5c578b3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jbowens/jBBCode/zipball/645b6a1c0afa92b7d029d3417ebd8b60a5c578b3",
|
||||
"reference": "645b6a1c0afa92b7d029d3417ebd8b60a5c578b3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "3.7.*"
|
||||
},
|
||||
"time": "2014-07-06 05:48:20",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"JBBCode": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jackson Owens",
|
||||
"email": "jackson_owens@alumni.brown.edu",
|
||||
"homepage": "http://jbowens.org/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A lightweight but extensible BBCode parser written in PHP 5.3.",
|
||||
"homepage": "http://jbbcode.com/",
|
||||
"keywords": [
|
||||
"BB",
|
||||
"bbcode"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "leafo/lessphp",
|
||||
"version": "v0.5.0",
|
||||
"version_normalized": "0.5.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/leafo/lessphp.git",
|
||||
"reference": "0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/leafo/lessphp/zipball/0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283",
|
||||
"reference": "0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283",
|
||||
"shasum": ""
|
||||
},
|
||||
"time": "2014-11-24 18:39:20",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.4.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"lessc.inc.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT",
|
||||
"GPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Leaf Corcoran",
|
||||
"email": "leafot@gmail.com",
|
||||
"homepage": "http://leafo.net"
|
||||
}
|
||||
],
|
||||
"description": "lessphp is a compiler for LESS written in PHP.",
|
||||
"homepage": "http://leafo.net/lessphp/"
|
||||
},
|
||||
{
|
||||
"name": "leafo/scssphp",
|
||||
"version": "v0.4.0",
|
||||
"version_normalized": "0.4.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/leafo/scssphp.git",
|
||||
"reference": "78a6f27aa4eaf70bb3ff4d13b639bab71fdaf47a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/leafo/scssphp/zipball/78a6f27aa4eaf70bb3ff4d13b639bab71fdaf47a",
|
||||
"reference": "78a6f27aa4eaf70bb3ff4d13b639bab71fdaf47a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"kherge/box": "~2.5",
|
||||
"phpunit/phpunit": "~3.7",
|
||||
"squizlabs/php_codesniffer": "~2.3"
|
||||
},
|
||||
"time": "2015-11-09 14:44:09",
|
||||
"bin": [
|
||||
"bin/pscss"
|
||||
],
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"classmap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Leafo\\ScssPhp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Leaf Corcoran",
|
||||
"email": "leafot@gmail.com",
|
||||
"homepage": "http://leafo.net"
|
||||
}
|
||||
],
|
||||
"description": "scssphp is a compiler for SCSS written in PHP.",
|
||||
"homepage": "http://leafo.github.io/scssphp/",
|
||||
"keywords": [
|
||||
"css",
|
||||
"less",
|
||||
"sass",
|
||||
"scss",
|
||||
"stylesheet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "4.2.0",
|
||||
"version_normalized": "4.2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/html-to-markdown.git",
|
||||
"reference": "9a5becc8c6b520920fb846afefcfd7faf4c31712"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/9a5becc8c6b520920fb846afefcfd7faf4c31712",
|
||||
"reference": "9a5becc8c6b520920fb846afefcfd7faf4c31712",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-xml": "*",
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikehaertl/php-shellcommand": "~1.1.0",
|
||||
"phpunit/phpunit": "4.*",
|
||||
"scrutinizer/ocular": "~1.1"
|
||||
},
|
||||
"time": "2016-02-01 16:49:02",
|
||||
"bin": [
|
||||
"bin/html-to-markdown"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.3-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\HTMLToMarkdown\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "http://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Nick Cernis",
|
||||
"email": "nick@cern.is",
|
||||
"homepage": "http://modernnerd.net",
|
||||
"role": "Original Author"
|
||||
}
|
||||
],
|
||||
"description": "An HTML-to-markdown conversion helper for PHP",
|
||||
"homepage": "https://github.com/thephpleague/html-to-markdown",
|
||||
"keywords": [
|
||||
"html",
|
||||
"markdown"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "michelf/php-smartypants",
|
||||
"version": "1.6.0-beta1",
|
||||
"version_normalized": "1.6.0.0-beta1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/michelf/php-smartypants.git",
|
||||
"reference": "c0465c6d4c5ab853c2fa45df6c10bce7e35cc137"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/michelf/php-smartypants/zipball/c0465c6d4c5ab853c2fa45df6c10bce7e35cc137",
|
||||
"reference": "c0465c6d4c5ab853c2fa45df6c10bce7e35cc137",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2013-07-31 18:13:10",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-lib": "1.6.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Michelf": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michel Fortin",
|
||||
"email": "michel.fortin@michelf.ca",
|
||||
"homepage": "http://michelf.ca/",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "John Gruber",
|
||||
"homepage": "http://daringfireball.net/"
|
||||
}
|
||||
],
|
||||
"description": "PHP SmartyPants",
|
||||
"homepage": "http://michelf.ca/projects/php-smartypants/",
|
||||
"keywords": [
|
||||
"dashes",
|
||||
"quotes",
|
||||
"spaces",
|
||||
"typographer",
|
||||
"typography"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
2
vendor/jbbcode/jbbcode/.gitignore
vendored
Normal file
2
vendor/jbbcode/jbbcode/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
composer.lock
|
||||
vendor
|
||||
328
vendor/jbbcode/jbbcode/JBBCode/CodeDefinition.php
vendored
Normal file
328
vendor/jbbcode/jbbcode/JBBCode/CodeDefinition.php
vendored
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
/**
|
||||
* This class represents a BBCode Definition. You may construct instances of this class directly,
|
||||
* usually through the CodeDefinitionBuilder class, to create text replacement bbcodes, or you
|
||||
* may subclass it to create more complex bbcode definitions.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class CodeDefinition
|
||||
{
|
||||
/* NOTE: THIS PROPERTY SHOULD ALWAYS BE LOWERCASE; USE setTagName() TO ENSURE THIS */
|
||||
protected $tagName;
|
||||
|
||||
/* Whether or not this CodeDefinition uses an option parameter. */
|
||||
protected $useOption;
|
||||
|
||||
/* The replacement text to be used for simple CodeDefinitions */
|
||||
protected $replacementText;
|
||||
|
||||
/* Whether or not to parse elements of this definition's contents */
|
||||
protected $parseContent;
|
||||
|
||||
/* How many of this element type may be nested within each other */
|
||||
protected $nestLimit;
|
||||
|
||||
/* How many of this element type have been seen */
|
||||
protected $elCounter;
|
||||
|
||||
/* The input validator to run options through */
|
||||
protected $optionValidator;
|
||||
|
||||
/* The input validator to run the body ({param}) through */
|
||||
protected $bodyValidator;
|
||||
|
||||
/**
|
||||
* Constructs a new CodeDefinition.
|
||||
*/
|
||||
public static function construct($tagName, $replacementText, $useOption = false,
|
||||
$parseContent = true, $nestLimit = -1, $optionValidator = array(),
|
||||
$bodyValidator = null)
|
||||
{
|
||||
$def = new CodeDefinition();
|
||||
$def->elCounter = 0;
|
||||
$def->setTagName($tagName);
|
||||
$def->setReplacementText($replacementText);
|
||||
$def->useOption = $useOption;
|
||||
$def->parseContent = $parseContent;
|
||||
$def->nestLimit = $nestLimit;
|
||||
$def->optionValidator = $optionValidator;
|
||||
$def->bodyValidator = $bodyValidator;
|
||||
return $def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new CodeDefinition.
|
||||
*
|
||||
* This constructor is deprecated. You should use the static construct() method or the
|
||||
* CodeDefinitionBuilder class to construct a new CodeDefiniton.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/* WARNING: This function is deprecated and will be made protected in a future
|
||||
* version of jBBCode. */
|
||||
$this->parseContent = true;
|
||||
$this->useOption = false;
|
||||
$this->nestLimit = -1;
|
||||
$this->elCounter = 0;
|
||||
$this->optionValidator = array();
|
||||
$this->bodyValidator = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the arguments to the given element are valid based on
|
||||
* any validators attached to this CodeDefinition.
|
||||
*
|
||||
* @param $el the ElementNode to validate
|
||||
* @return true if the ElementNode's {option} and {param} are OK, false if they're not
|
||||
*/
|
||||
public function hasValidInputs(ElementNode $el)
|
||||
{
|
||||
if ($this->usesOption() && $this->optionValidator) {
|
||||
$att = $el->getAttribute();
|
||||
|
||||
foreach($att as $name => $value){
|
||||
if(isset($this->optionValidator[$name]) && !$this->optionValidator[$name]->validate($value)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->parseContent() && $this->bodyValidator) {
|
||||
/* We only evaluate the content if we're not parsing the content. */
|
||||
$content = "";
|
||||
foreach ($el->getChildren() as $child) {
|
||||
$content .= $child->getAsBBCode();
|
||||
}
|
||||
if (!$this->bodyValidator->validate($content)) {
|
||||
/* The content of the element is not valid. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts an ElementNode that is defined by this CodeDefinition and returns the HTML
|
||||
* markup of the element. This is a commonly overridden class for custom CodeDefinitions
|
||||
* so that the content can be directly manipulated.
|
||||
*
|
||||
* @param $el the element to return an html representation of
|
||||
*
|
||||
* @return the parsed html of this element (INCLUDING ITS CHILDREN)
|
||||
*/
|
||||
public function asHtml(ElementNode $el)
|
||||
{
|
||||
if (!$this->hasValidInputs($el)) {
|
||||
return $el->getAsBBCode();
|
||||
}
|
||||
|
||||
$html = $this->getReplacementText();
|
||||
|
||||
if ($this->usesOption()) {
|
||||
$options = $el->getAttribute();
|
||||
if(count($options)==1){
|
||||
$vals = array_values($options);
|
||||
$html = str_ireplace('{option}', reset($vals), $html);
|
||||
}
|
||||
else{
|
||||
foreach($options as $key => $val){
|
||||
$html = str_ireplace('{' . $key . '}', $val, $html);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$content = $this->getContent($el);
|
||||
|
||||
$html = str_ireplace('{param}', $content, $html);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
protected function getContent(ElementNode $el){
|
||||
if ($this->parseContent()) {
|
||||
$content = "";
|
||||
foreach ($el->getChildren() as $child)
|
||||
$content .= $child->getAsHTML();
|
||||
} else {
|
||||
$content = "";
|
||||
foreach ($el->getChildren() as $child)
|
||||
$content .= $child->getAsBBCode();
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts an ElementNode that is defined by this CodeDefinition and returns the text
|
||||
* representation of the element. This may be overridden by a custom CodeDefinition.
|
||||
*
|
||||
* @param $el the element to return a text representation of
|
||||
*
|
||||
* @return the text representation of $el
|
||||
*/
|
||||
public function asText(ElementNode $el)
|
||||
{
|
||||
if (!$this->hasValidInputs($el)) {
|
||||
return $el->getAsBBCode();
|
||||
}
|
||||
|
||||
$s = "";
|
||||
foreach ($el->getChildren() as $child)
|
||||
$s .= $child->getAsText();
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tag name of this code definition
|
||||
*
|
||||
* @return this definition's associated tag name
|
||||
*/
|
||||
public function getTagName()
|
||||
{
|
||||
return $this->tagName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the replacement text of this code definition. This usually has little, if any meaning if the
|
||||
* CodeDefinition class was extended. For default, html replacement CodeDefinitions this returns the html
|
||||
* markup for the definition.
|
||||
*
|
||||
* @return the replacement text of this CodeDefinition
|
||||
*/
|
||||
public function getReplacementText()
|
||||
{
|
||||
return $this->replacementText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this CodeDefinition uses the optional {option}
|
||||
*
|
||||
* @return true if this CodeDefinition uses the option, false otherwise
|
||||
*/
|
||||
public function usesOption()
|
||||
{
|
||||
return $this->useOption;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this CodeDefnition parses elements contained within it,
|
||||
* or just treats its children as text.
|
||||
*
|
||||
* @return true if this CodeDefinition parses elements contained within itself
|
||||
*/
|
||||
public function parseContent()
|
||||
{
|
||||
return $this->parseContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the limit of how many elements defined by this CodeDefinition may be
|
||||
* nested together. If after parsing elements are nested beyond this limit, the
|
||||
* subtrees formed by those nodes will be removed from the parse tree. A nest
|
||||
* limit of -1 signifies no limit.
|
||||
*/
|
||||
public function getNestLimit()
|
||||
{
|
||||
return $this->nestLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag name of this CodeDefinition
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param the new tag name of this definition
|
||||
*/
|
||||
public function setTagName($tagName)
|
||||
{
|
||||
$this->tagName = strtolower($tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the html replacement text of this CodeDefinition
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param the new replacement text
|
||||
*/
|
||||
public function setReplacementText($txt)
|
||||
{
|
||||
$this->replacementText = $txt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not this CodeDefinition uses the {option}
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param boolean $bool
|
||||
*/
|
||||
public function setUseOption($bool)
|
||||
{
|
||||
$this->useOption = $bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not this CodeDefinition allows its children to be parsed as html
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param boolean $bool
|
||||
*/
|
||||
public function setParseContent($bool)
|
||||
{
|
||||
$this->parseContent = $bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the element counter. This is used for tracking depth of elements of the same type for next limits.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function incrementCounter()
|
||||
{
|
||||
$this->elCounter++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements the element counter.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function decrementCounter()
|
||||
{
|
||||
$this->elCounter--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the element counter.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function resetCounter()
|
||||
{
|
||||
$this->elCounter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the element counter.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCounter()
|
||||
{
|
||||
return $this->elCounter;
|
||||
}
|
||||
}
|
||||
160
vendor/jbbcode/jbbcode/JBBCode/CodeDefinitionBuilder.php
vendored
Normal file
160
vendor/jbbcode/jbbcode/JBBCode/CodeDefinitionBuilder.php
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
require_once "CodeDefinition.php";
|
||||
|
||||
/**
|
||||
* Implements the builder pattern for the CodeDefinition class. A builder
|
||||
* is the recommended way of constructing CodeDefinition objects.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class CodeDefinitionBuilder
|
||||
{
|
||||
|
||||
protected $tagName;
|
||||
protected $useOption = false;
|
||||
protected $replacementText;
|
||||
protected $parseContent = true;
|
||||
protected $nestLimit = -1;
|
||||
protected $optionValidator = array();
|
||||
protected $bodyValidator = null;
|
||||
|
||||
/**
|
||||
* Construct a CodeDefinitionBuilder.
|
||||
*
|
||||
* @param $tagName the tag name of the definition to build
|
||||
* @param $replacementText the replacement text of the definition to build
|
||||
*/
|
||||
public function __construct($tagName, $replacementText)
|
||||
{
|
||||
$this->tagName = $tagName;
|
||||
$this->replacementText = $replacementText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag name the CodeDefinition should be built with.
|
||||
*
|
||||
* @param $tagName the tag name for the new CodeDefinition
|
||||
*/
|
||||
public function setTagName($tagName)
|
||||
{
|
||||
$this->tagName = $tagName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the replacement text that the new CodeDefinition should be
|
||||
* built with.
|
||||
*
|
||||
* @param $replacementText the replacement text for the new CodeDefinition
|
||||
*/
|
||||
public function setReplacementText($replacementText)
|
||||
{
|
||||
$this->replacementText = $replacementText;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not the built CodeDefinition should use the {option} bbcode
|
||||
* argument.
|
||||
*
|
||||
* @param $option ture iff the definition includes an option
|
||||
*/
|
||||
public function setUseOption($option)
|
||||
{
|
||||
$this->useOption = $option;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not the built CodeDefinition should allow its content
|
||||
* to be parsed and evaluated as bbcode.
|
||||
*
|
||||
* @param $parseContent true iff the content should be parsed
|
||||
*/
|
||||
public function setParseContent($parseContent)
|
||||
{
|
||||
$this->parseContent = $parseContent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nest limit for this code definition.
|
||||
*
|
||||
* @param $nestLimit a positive integer, or -1 if there is no limit.
|
||||
* @throws \InvalidArgumentException if the nest limit is invalid
|
||||
*/
|
||||
public function setNestLimit($limit)
|
||||
{
|
||||
if(!is_int($limit) || ($limit <= 0 && -1 != $limit)) {
|
||||
throw new \InvalidArgumentException("A nest limit must be a positive integer " .
|
||||
"or -1.");
|
||||
}
|
||||
$this->nestLimit = $limit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the InputValidator that option arguments should be validated with.
|
||||
*
|
||||
* @param $validator the InputValidator instance to use
|
||||
*/
|
||||
public function setOptionValidator(\JBBCode\InputValidator $validator, $option=null)
|
||||
{
|
||||
if(empty($option)){
|
||||
$option = $this->tagName;
|
||||
}
|
||||
$this->optionValidator[$option] = $validator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the InputValidator that body ({param}) text should be validated with.
|
||||
*
|
||||
* @param $validator the InputValidator instance to use
|
||||
*/
|
||||
public function setBodyValidator(\JBBCode\InputValidator $validator)
|
||||
{
|
||||
$this->bodyValidator = $validator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the attached option validator if one is attached.
|
||||
*/
|
||||
public function removeOptionValidator()
|
||||
{
|
||||
$this->optionValidator = array();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the attached body validator if one is attached.
|
||||
*/
|
||||
public function removeBodyValidator()
|
||||
{
|
||||
$this->bodyValidator = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CodeDefinition with the current state of the builder.
|
||||
*
|
||||
* @return a new CodeDefinition instance
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$definition = CodeDefinition::construct($this->tagName,
|
||||
$this->replacementText,
|
||||
$this->useOption,
|
||||
$this->parseContent,
|
||||
$this->nestLimit,
|
||||
$this->optionValidator,
|
||||
$this->bodyValidator);
|
||||
return $definition;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
22
vendor/jbbcode/jbbcode/JBBCode/CodeDefinitionSet.php
vendored
Normal file
22
vendor/jbbcode/jbbcode/JBBCode/CodeDefinitionSet.php
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
require_once 'CodeDefinition.php';
|
||||
|
||||
use JBBCode\CodeDefinition;
|
||||
|
||||
/**
|
||||
* An interface for sets of code definitons.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
interface CodeDefinitionSet
|
||||
{
|
||||
|
||||
/**
|
||||
* Retrieves the CodeDefinitions within this set as an array.
|
||||
*/
|
||||
public function getCodeDefinitions();
|
||||
|
||||
}
|
||||
75
vendor/jbbcode/jbbcode/JBBCode/DefaultCodeDefinitionSet.php
vendored
Normal file
75
vendor/jbbcode/jbbcode/JBBCode/DefaultCodeDefinitionSet.php
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
require_once 'CodeDefinition.php';
|
||||
require_once 'CodeDefinitionBuilder.php';
|
||||
require_once 'CodeDefinitionSet.php';
|
||||
require_once 'validators/CssColorValidator.php';
|
||||
require_once 'validators/UrlValidator.php';
|
||||
|
||||
/**
|
||||
* Provides a default set of common bbcode definitions.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class DefaultCodeDefinitionSet implements CodeDefinitionSet
|
||||
{
|
||||
|
||||
/* The default code definitions in this set. */
|
||||
protected $definitions = array();
|
||||
|
||||
/**
|
||||
* Constructs the default code definitions.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/* [b] bold tag */
|
||||
$builder = new CodeDefinitionBuilder('b', '<strong>{param}</strong>');
|
||||
array_push($this->definitions, $builder->build());
|
||||
|
||||
/* [i] italics tag */
|
||||
$builder = new CodeDefinitionBuilder('i', '<em>{param}</em>');
|
||||
array_push($this->definitions, $builder->build());
|
||||
|
||||
/* [u] underline tag */
|
||||
$builder = new CodeDefinitionBuilder('u', '<u>{param}</u>');
|
||||
array_push($this->definitions, $builder->build());
|
||||
|
||||
$urlValidator = new \JBBCode\validators\UrlValidator();
|
||||
|
||||
/* [url] link tag */
|
||||
$builder = new CodeDefinitionBuilder('url', '<a href="{param}">{param}</a>');
|
||||
$builder->setParseContent(false)->setBodyValidator($urlValidator);
|
||||
array_push($this->definitions, $builder->build());
|
||||
|
||||
/* [url=http://example.com] link tag */
|
||||
$builder = new CodeDefinitionBuilder('url', '<a href="{option}">{param}</a>');
|
||||
$builder->setUseOption(true)->setParseContent(true)->setOptionValidator($urlValidator);
|
||||
array_push($this->definitions, $builder->build());
|
||||
|
||||
/* [img] image tag */
|
||||
$builder = new CodeDefinitionBuilder('img', '<img src="{param}" />');
|
||||
$builder->setUseOption(false)->setParseContent(false)->setBodyValidator($urlValidator);
|
||||
array_push($this->definitions, $builder->build());
|
||||
|
||||
/* [img=alt text] image tag */
|
||||
$builder = new CodeDefinitionBuilder('img', '<img src="{param}" alt="{option}" />');
|
||||
$builder->setUseOption(true)->setParseContent(false)->setBodyValidator($urlValidator);
|
||||
array_push($this->definitions, $builder->build());
|
||||
|
||||
/* [color] color tag */
|
||||
$builder = new CodeDefinitionBuilder('color', '<span style="color: {option}">{param}</span>');
|
||||
$builder->setUseOption(true)->setOptionValidator(new \JBBCode\validators\CssColorValidator());
|
||||
array_push($this->definitions, $builder->build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the default code definitions.
|
||||
*/
|
||||
public function getCodeDefinitions()
|
||||
{
|
||||
return $this->definitions;
|
||||
}
|
||||
|
||||
}
|
||||
67
vendor/jbbcode/jbbcode/JBBCode/DocumentElement.php
vendored
Normal file
67
vendor/jbbcode/jbbcode/JBBCode/DocumentElement.php
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
require_once 'ElementNode.php';
|
||||
|
||||
/**
|
||||
* A DocumentElement object represents the root of a document tree. All
|
||||
* documents represented by this document model should have one as its root.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class DocumentElement extends ElementNode
|
||||
{
|
||||
/**
|
||||
* Constructs the document element node
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->setTagName("Document");
|
||||
$this->setNodeId(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.ElementNode::getAsBBCode()
|
||||
*
|
||||
* Returns the BBCode representation of this document
|
||||
*
|
||||
* @return this document's bbcode representation
|
||||
*/
|
||||
public function getAsBBCode()
|
||||
{
|
||||
$s = "";
|
||||
foreach($this->getChildren() as $child){
|
||||
$s .= $child->getAsBBCode();
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.ElementNode::getAsHTML()
|
||||
*
|
||||
* Documents don't add any html. They only exist as a container for their
|
||||
* children, so getAsHTML() simply iterates through the document's children,
|
||||
* returning their html.
|
||||
*
|
||||
* @return the HTML representation of this document
|
||||
*/
|
||||
public function getAsHTML()
|
||||
{
|
||||
$s = "";
|
||||
foreach($this->getChildren() as $child)
|
||||
$s .= $child->getAsHTML();
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
public function accept(NodeVisitor $visitor)
|
||||
{
|
||||
$visitor->visitDocumentElement($this);
|
||||
}
|
||||
|
||||
}
|
||||
241
vendor/jbbcode/jbbcode/JBBCode/ElementNode.php
vendored
Normal file
241
vendor/jbbcode/jbbcode/JBBCode/ElementNode.php
vendored
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
require_once 'Node.php';
|
||||
|
||||
/**
|
||||
* An element within the tree. Consists of a tag name which defines the type of the
|
||||
* element and any number of Node children. It also contains a CodeDefinition matching
|
||||
* the tag name of the element.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class ElementNode extends Node
|
||||
{
|
||||
/* The tagname of this element, for i.e. "b" in [b]bold[/b] */
|
||||
protected $tagName;
|
||||
|
||||
/* The attribute, if any, of this element node */
|
||||
protected $attribute;
|
||||
|
||||
/* The child nodes contained within this element */
|
||||
protected $children;
|
||||
|
||||
/* The code definition that defines this element's behavior */
|
||||
protected $codeDefinition;
|
||||
|
||||
/* How deeply this node is nested */
|
||||
protected $nestDepth;
|
||||
|
||||
/**
|
||||
* Constructs the element node
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->children = array();
|
||||
$this->nestDepth = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts the given NodeVisitor. This is part of an implementation
|
||||
* of the Visitor pattern.
|
||||
*
|
||||
* @param $nodeVisitor the visitor attempting to visit this node
|
||||
*/
|
||||
public function accept(NodeVisitor $nodeVisitor)
|
||||
{
|
||||
$nodeVisitor->visitElementNode($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CodeDefinition that defines this element.
|
||||
*
|
||||
* @return this element's code definition
|
||||
*/
|
||||
public function getCodeDefinition()
|
||||
{
|
||||
return $this->codeDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CodeDefinition that defines this element.
|
||||
*
|
||||
* @param codeDef the code definition that defines this element node
|
||||
*/
|
||||
public function setCodeDefinition(CodeDefinition $codeDef)
|
||||
{
|
||||
$this->codeDefinition = $codeDef;
|
||||
$this->setTagName($codeDef->getTagName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tag name of this element.
|
||||
*
|
||||
* @return the element's tag name
|
||||
*/
|
||||
public function getTagName()
|
||||
{
|
||||
return $this->tagName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute (used as the option in bbcode definitions) of this element.
|
||||
*
|
||||
* @return the attribute of this element
|
||||
*/
|
||||
public function getAttribute()
|
||||
{
|
||||
return $this->attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the children of this element.
|
||||
*
|
||||
* @return an array of this node's child nodes
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.Node::getAsText()
|
||||
*
|
||||
* Returns the element as text (not including any bbcode markup)
|
||||
*
|
||||
* @return the plain text representation of this node
|
||||
*/
|
||||
public function getAsText()
|
||||
{
|
||||
if ($this->codeDefinition) {
|
||||
return $this->codeDefinition->asText($this);
|
||||
} else {
|
||||
$s = "";
|
||||
foreach ($this->getChildren() as $child)
|
||||
$s .= $child->getAsText();
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.Node::getAsBBCode()
|
||||
*
|
||||
* Returns the element as bbcode (with all unclosed tags closed)
|
||||
*
|
||||
* @return the bbcode representation of this element
|
||||
*/
|
||||
public function getAsBBCode()
|
||||
{
|
||||
$str = "[".$this->tagName;
|
||||
if (!empty($this->attribute)) {
|
||||
|
||||
foreach($this->attribute as $key => $value){
|
||||
if($key == $this->tagName){
|
||||
$str .= "=".$value;
|
||||
}
|
||||
else{
|
||||
$str .= " ".$key."=" . $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
$str .= "]";
|
||||
foreach ($this->getChildren() as $child) {
|
||||
$str .= $child->getAsBBCode();
|
||||
}
|
||||
$str .= "[/".$this->tagName."]";
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.Node::getAsHTML()
|
||||
*
|
||||
* Returns the element as html with all replacements made
|
||||
*
|
||||
* @return the html representation of this node
|
||||
*/
|
||||
public function getAsHTML()
|
||||
{
|
||||
if($this->codeDefinition) {
|
||||
return $this->codeDefinition->asHtml($this);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child to this node's content. A child may be a TextNode, or
|
||||
* another ElementNode... or anything else that may extend the
|
||||
* abstract Node class.
|
||||
*
|
||||
* @param child the node to add as a child
|
||||
*/
|
||||
public function addChild(Node $child)
|
||||
{
|
||||
array_push($this->children, $child);
|
||||
$child->setParent($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a child from this node's contnet.
|
||||
*
|
||||
* @param child the child node to remove
|
||||
*/
|
||||
public function removeChild(Node $child)
|
||||
{
|
||||
foreach ($this->children as $key => $value) {
|
||||
if ($value == $child)
|
||||
unset($this->children[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag name of this element node.
|
||||
*
|
||||
* @param tagName the element's new tag name
|
||||
*/
|
||||
public function setTagName($tagName)
|
||||
{
|
||||
$this->tagName = $tagName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute (option) of this element node.
|
||||
*
|
||||
* @param attribute the attribute of this element node
|
||||
*/
|
||||
public function setAttribute($attribute)
|
||||
{
|
||||
$this->attribute = $attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the parse tree upwards, going from parent to parent, until it finds a
|
||||
* parent who has the given tag name. Returns the parent with the matching tag name
|
||||
* if it exists, otherwise returns null.
|
||||
*
|
||||
* @param str the tag name to search for
|
||||
*
|
||||
* @return the closest parent with the given tag name
|
||||
*/
|
||||
public function closestParentOfType($str)
|
||||
{
|
||||
$str = strtolower($str);
|
||||
$currentEl = $this;
|
||||
|
||||
while (strtolower($currentEl->getTagName()) != $str && $currentEl->hasParent()) {
|
||||
$currentEl = $currentEl->getParent();
|
||||
}
|
||||
|
||||
if (strtolower($currentEl->getTagName()) != $str) {
|
||||
return null;
|
||||
} else {
|
||||
return $currentEl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
20
vendor/jbbcode/jbbcode/JBBCode/InputValidator.php
vendored
Normal file
20
vendor/jbbcode/jbbcode/JBBCode/InputValidator.php
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
/**
|
||||
* Defines an interface for validation filters for bbcode options and
|
||||
* parameters.
|
||||
*
|
||||
* @author jbowens
|
||||
* @since May 2013
|
||||
*/
|
||||
interface InputValidator
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns true iff the given input is valid, false otherwise.
|
||||
*/
|
||||
public function validate($input);
|
||||
|
||||
}
|
||||
109
vendor/jbbcode/jbbcode/JBBCode/Node.php
vendored
Normal file
109
vendor/jbbcode/jbbcode/JBBCode/Node.php
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
/**
|
||||
* A node within the document tree.
|
||||
*
|
||||
* Known subclasses: TextNode, ElementNode
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
abstract class Node
|
||||
{
|
||||
/* Pointer to the parent node of this node */
|
||||
protected $parent;
|
||||
|
||||
/* The node id of this node */
|
||||
protected $nodeid;
|
||||
|
||||
/**
|
||||
* Returns the node id of this node. (Not really ever used. Dependent upon the parse tree the node exists within.)
|
||||
*
|
||||
* @return this node's id
|
||||
*/
|
||||
public function getNodeId()
|
||||
{
|
||||
return $this->nodeid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this node's immediate parent.
|
||||
*
|
||||
* @return the node's parent
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this node has a parent.
|
||||
*
|
||||
* @return true if this node has a parent, false otherwise
|
||||
*/
|
||||
public function hasParent()
|
||||
{
|
||||
return $this->parent != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a text node. Returns false otherwise.
|
||||
* (Overridden by TextNode to return true)
|
||||
*
|
||||
* @return true if this node is a text node
|
||||
*/
|
||||
public function isTextNode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a NodeVisitor
|
||||
*
|
||||
* @param nodeVisitor the NodeVisitor traversing the graph
|
||||
*/
|
||||
abstract public function accept(NodeVisitor $nodeVisitor);
|
||||
|
||||
/**
|
||||
* Returns this node as text (without any bbcode markup)
|
||||
*
|
||||
* @return the plain text representation of this node
|
||||
*/
|
||||
abstract public function getAsText();
|
||||
|
||||
/**
|
||||
* Returns this node as bbcode
|
||||
*
|
||||
* @return the bbcode representation of this node
|
||||
*/
|
||||
abstract public function getAsBBCode();
|
||||
|
||||
/**
|
||||
* Returns this node as HTML
|
||||
*
|
||||
* @return the html representation of this node
|
||||
*/
|
||||
abstract public function getAsHTML();
|
||||
|
||||
/**
|
||||
* Sets this node's parent to be the given node.
|
||||
*
|
||||
* @param parent the node to set as this node's parent
|
||||
*/
|
||||
public function setParent(Node $parent)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this node's nodeid
|
||||
*
|
||||
* @param nodeid this node's node id
|
||||
*/
|
||||
public function setNodeId($nodeid)
|
||||
{
|
||||
$this->nodeid = $nodeid;
|
||||
}
|
||||
|
||||
}
|
||||
20
vendor/jbbcode/jbbcode/JBBCode/NodeVisitor.php
vendored
Normal file
20
vendor/jbbcode/jbbcode/JBBCode/NodeVisitor.php
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
/**
|
||||
* Defines an interface for a visitor to traverse the node graph.
|
||||
*
|
||||
* @author jbowens
|
||||
* @since January 2013
|
||||
*/
|
||||
interface NodeVisitor
|
||||
{
|
||||
|
||||
public function visitDocumentElement(DocumentElement $documentElement);
|
||||
|
||||
public function visitTextNode(TextNode $textNode);
|
||||
|
||||
public function visitElementNode(ElementNode $elementNode);
|
||||
|
||||
}
|
||||
662
vendor/jbbcode/jbbcode/JBBCode/Parser.php
vendored
Normal file
662
vendor/jbbcode/jbbcode/JBBCode/Parser.php
vendored
Normal file
|
|
@ -0,0 +1,662 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
require_once 'ElementNode.php';
|
||||
require_once 'TextNode.php';
|
||||
require_once 'DefaultCodeDefinitionSet.php';
|
||||
require_once 'DocumentElement.php';
|
||||
require_once 'CodeDefinition.php';
|
||||
require_once 'CodeDefinitionBuilder.php';
|
||||
require_once 'CodeDefinitionSet.php';
|
||||
require_once 'NodeVisitor.php';
|
||||
require_once 'ParserException.php';
|
||||
require_once 'Tokenizer.php';
|
||||
require_once 'visitors/NestLimitVisitor.php';
|
||||
require_once 'InputValidator.php';
|
||||
|
||||
use JBBCode\CodeDefinition;
|
||||
|
||||
/**
|
||||
* BBCodeParser is the main parser class that constructs and stores the parse tree. Through this class
|
||||
* new bbcode definitions can be added, and documents may be parsed and converted to html/bbcode/plaintext, etc.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class Parser
|
||||
{
|
||||
|
||||
const OPTION_STATE_DEFAULT = 0;
|
||||
const OPTION_STATE_TAGNAME = 1;
|
||||
const OPTION_STATE_KEY = 2;
|
||||
const OPTION_STATE_VALUE = 3;
|
||||
const OPTION_STATE_QUOTED_VALUE = 4;
|
||||
const OPTION_STATE_JAVASCRIPT = 5;
|
||||
|
||||
/* The root element of the parse tree */
|
||||
protected $treeRoot;
|
||||
|
||||
/* The list of bbcodes to be used by the parser. */
|
||||
protected $bbcodes;
|
||||
|
||||
/* The next node id to use. This is used while parsing. */
|
||||
protected $nextNodeid;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the BBCode parser
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->reset();
|
||||
$this->bbcodes = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a simple (text-replacement only) bbcode definition
|
||||
*
|
||||
* @param string $tagName the tag name of the code (for example the b in [b])
|
||||
* @param string $replace the html to use, with {param} and optionally {option} for replacements
|
||||
* @param boolean $useOption whether or not this bbcode uses the secondary {option} replacement
|
||||
* @param boolean $parseContent whether or not to parse the content within these elements
|
||||
* @param integer $nestLimit an optional limit of the number of elements of this kind that can be nested within
|
||||
* each other before the parser stops parsing them.
|
||||
* @param InputValidator $optionValidator the validator to run {option} through
|
||||
* @param BodyValidator $bodyValidator the validator to run {param} through (only used if $parseContent == false)
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
public function addBBCode($tagName, $replace, $useOption = false, $parseContent = true, $nestLimit = -1,
|
||||
InputValidator $optionValidator = null, InputValidator $bodyValidator = null)
|
||||
{
|
||||
$builder = new CodeDefinitionBuilder($tagName, $replace);
|
||||
|
||||
$builder->setUseOption($useOption);
|
||||
$builder->setParseContent($parseContent);
|
||||
$builder->setNestLimit($nestLimit);
|
||||
|
||||
if ($optionValidator) {
|
||||
$builder->setOptionValidator($optionValidator);
|
||||
}
|
||||
|
||||
if ($bodyValidator) {
|
||||
$builder->setBodyValidator($bodyValidator);
|
||||
}
|
||||
|
||||
$this->addCodeDefinition($builder->build());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a complex bbcode definition. You may subclass the CodeDefinition class, instantiate a definition of your new
|
||||
* class and add it to the parser through this method.
|
||||
*
|
||||
* @param CodeDefinition $definition the bbcode definition to add
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
public function addCodeDefinition(CodeDefinition $definition)
|
||||
{
|
||||
array_push($this->bbcodes, $definition);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a set of CodeDefinitions.
|
||||
*
|
||||
* @param CodeDefinitionSet $set the set of definitions to add
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
public function addCodeDefinitionSet(CodeDefinitionSet $set) {
|
||||
foreach ($set->getCodeDefinitions() as $def) {
|
||||
$this->addCodeDefinition($def);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entire parse tree as text. Only {param} content is returned. BBCode markup will be ignored.
|
||||
*
|
||||
* @return string a text representation of the parse tree
|
||||
*/
|
||||
public function getAsText()
|
||||
{
|
||||
return $this->treeRoot->getAsText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entire parse tree as bbcode. This will be identical to the inputted string, except unclosed tags
|
||||
* will be closed.
|
||||
*
|
||||
* @return string a bbcode representation of the parse tree
|
||||
*/
|
||||
public function getAsBBCode()
|
||||
{
|
||||
return $this->treeRoot->getAsBBCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entire parse tree as HTML. All BBCode replacements will be made. This is generally the method
|
||||
* you will want to use to retrieve the parsed bbcode.
|
||||
*
|
||||
* @return string a parsed html string
|
||||
*/
|
||||
public function getAsHTML()
|
||||
{
|
||||
return $this->treeRoot->getAsHTML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts the given NodeVisitor at the root.
|
||||
*
|
||||
* @param NodeVisitor a NodeVisitor
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
public function accept(NodeVisitor $nodeVisitor)
|
||||
{
|
||||
$this->treeRoot->accept($nodeVisitor);
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Constructs the parse tree from a string of bbcode markup.
|
||||
*
|
||||
* @param string $str the bbcode markup to parse
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
public function parse($str)
|
||||
{
|
||||
/* Set the tree root back to a fresh DocumentElement. */
|
||||
$this->reset();
|
||||
|
||||
$parent = $this->treeRoot;
|
||||
$tokenizer = new Tokenizer($str);
|
||||
|
||||
while ($tokenizer->hasNext()) {
|
||||
$parent = $this->parseStartState($parent, $tokenizer);
|
||||
if ($parent->getCodeDefinition() && false ===
|
||||
$parent->getCodeDefinition()->parseContent()) {
|
||||
/* We're inside an element that does not allow its contents to be parseable. */
|
||||
$this->parseAsTextUntilClose($parent, $tokenizer);
|
||||
$parent = $parent->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/* We parsed ignoring nest limits. Do an O(n) traversal to remove any elements that
|
||||
* are nested beyond their CodeDefinition's nest limit. */
|
||||
$this->removeOverNestedElements();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any elements that are nested beyond their nest limit from the parse tree. This
|
||||
* method is now deprecated. In a future release its access privileges will be made
|
||||
* protected.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function removeOverNestedElements()
|
||||
{
|
||||
$nestLimitVisitor = new \JBBCode\visitors\NestLimitVisitor();
|
||||
$this->accept($nestLimitVisitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the old parse tree if one exists.
|
||||
*/
|
||||
protected function reset()
|
||||
{
|
||||
// remove any old tree information
|
||||
$this->treeRoot = new DocumentElement();
|
||||
/* The document element is created with nodeid 0. */
|
||||
$this->nextNodeid = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a bbcode exists based on its tag name and whether or not it uses an option
|
||||
*
|
||||
* @param string $tagName the bbcode tag name to check
|
||||
* @param boolean $usesOption whether or not the bbcode accepts an option
|
||||
*
|
||||
* @return bool true if the code exists, false otherwise
|
||||
*/
|
||||
public function codeExists($tagName, $usesOption = false)
|
||||
{
|
||||
foreach ($this->bbcodes as $code) {
|
||||
if (strtolower($tagName) == $code->getTagName() && $usesOption == $code->usesOption()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CodeDefinition of a bbcode with the matching tag name and usesOption parameter
|
||||
*
|
||||
* @param string $tagName the tag name of the bbcode being searched for
|
||||
* @param boolean $usesOption whether or not the bbcode accepts an option
|
||||
*
|
||||
* @return CodeDefinition if the bbcode exists, null otherwise
|
||||
*/
|
||||
public function getCode($tagName, $usesOption = false)
|
||||
{
|
||||
foreach ($this->bbcodes as $code) {
|
||||
if (strtolower($tagName) == $code->getTagName() && $code->usesOption() == $usesOption) {
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a set of default, standard bbcode definitions commonly used across the web.
|
||||
*
|
||||
* This method is now deprecated. Please use DefaultCodeDefinitionSet and
|
||||
* addCodeDefinitionSet() instead.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function loadDefaultCodes()
|
||||
{
|
||||
$defaultSet = new DefaultCodeDefinitionSet();
|
||||
$this->addCodeDefinitionSet($defaultSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new text node with the given parent and text string.
|
||||
*
|
||||
* @param $parent the parent of the text node
|
||||
* @param $string the text of the text node
|
||||
*
|
||||
* @return TextNode the newly created TextNode
|
||||
*/
|
||||
protected function createTextNode(ElementNode $parent, $string)
|
||||
{
|
||||
if (count($parent->getChildren())) {
|
||||
$children = $parent->getChildren();
|
||||
$lastElement = end($children);
|
||||
reset($children);
|
||||
|
||||
if ($lastElement->isTextNode()) {
|
||||
$lastElement->setValue($lastElement->getValue() . $string);
|
||||
return $lastElement;
|
||||
}
|
||||
}
|
||||
|
||||
$textNode = new TextNode($string);
|
||||
$textNode->setNodeId(++$this->nextNodeid);
|
||||
$parent->addChild($textNode);
|
||||
return $textNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* jBBCode parsing logic is loosely modelled after a FSM. While not every function maps
|
||||
* to a unique DFSM state, each function handles the logic of one or more FSM states.
|
||||
* This function handles the beginning parse state when we're not currently in a tag
|
||||
* name.
|
||||
*
|
||||
* @param ElementNode $parent the current parent node we're under
|
||||
* @param Tokenizer $tokenizer the tokenizer we're using
|
||||
*
|
||||
* @return ElementNode the new parent we should use for the next iteration.
|
||||
*/
|
||||
protected function parseStartState(ElementNode $parent, Tokenizer $tokenizer)
|
||||
{
|
||||
$next = $tokenizer->next();
|
||||
|
||||
if ('[' == $next) {
|
||||
return $this->parseTagOpen($parent, $tokenizer);
|
||||
}
|
||||
else {
|
||||
$this->createTextNode($parent, $next);
|
||||
/* Drop back into the main parse loop which will call this
|
||||
* same method again. */
|
||||
return $parent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function handles parsing the beginnings of an open tag. When we see a [
|
||||
* at an appropriate time, this function is entered.
|
||||
*
|
||||
* @param ElementNode $parent the current parent node
|
||||
* @param Tokenizer $tokenizer the tokenizer we're using
|
||||
*
|
||||
* @return ElementNode the new parent node
|
||||
*/
|
||||
protected function parseTagOpen(ElementNode $parent, Tokenizer $tokenizer)
|
||||
{
|
||||
|
||||
if (!$tokenizer->hasNext()) {
|
||||
/* The [ that sent us to this state was just a trailing [, not the
|
||||
* opening for a new tag. Treat it as such. */
|
||||
$this->createTextNode($parent, '[');
|
||||
return $parent;
|
||||
}
|
||||
|
||||
$next = $tokenizer->next();
|
||||
|
||||
/* This while loop could be replaced by a recursive call to this same method,
|
||||
* which would likely be a lot clearer but I decided to use a while loop to
|
||||
* prevent stack overflow with a string like [[[[[[[[[...[[[.
|
||||
*/
|
||||
while ('[' == $next) {
|
||||
/* The previous [ was just a random bracket that should be treated as text.
|
||||
* Continue until we get a non open bracket. */
|
||||
$this->createTextNode($parent, '[');
|
||||
if (!$tokenizer->hasNext()) {
|
||||
$this->createTextNode($parent, '[');
|
||||
return $parent;
|
||||
}
|
||||
$next = $tokenizer->next();
|
||||
}
|
||||
|
||||
if (!$tokenizer->hasNext()) {
|
||||
$this->createTextNode($parent, '['.$next);
|
||||
return $parent;
|
||||
}
|
||||
|
||||
$after_next = $tokenizer->next();
|
||||
$tokenizer->stepBack();
|
||||
|
||||
if ($after_next != ']')
|
||||
{
|
||||
$this->createTextNode($parent, '['.$next);
|
||||
return $parent;
|
||||
}
|
||||
|
||||
/* At this point $next is either ']' or plain text. */
|
||||
if (']' == $next) {
|
||||
$this->createTextNode($parent, '[');
|
||||
$this->createTextNode($parent, ']');
|
||||
return $parent;
|
||||
} else {
|
||||
/* $next is plain text... likely a tag name. */
|
||||
return $this->parseTag($parent, $tokenizer, $next);
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseOptions($tagContent)
|
||||
{
|
||||
$buffer = "";
|
||||
$tagName = "";
|
||||
$state = static::OPTION_STATE_TAGNAME;
|
||||
$keys = array();
|
||||
$values = array();
|
||||
$options = array();
|
||||
|
||||
$len = strlen($tagContent);
|
||||
$done = false;
|
||||
$idx = 0;
|
||||
|
||||
try{
|
||||
while(!$done){
|
||||
$char = $idx < $len ? $tagContent[$idx]:null;
|
||||
switch($state){
|
||||
case static::OPTION_STATE_TAGNAME:
|
||||
switch($char){
|
||||
case '=':
|
||||
$state = static::OPTION_STATE_VALUE;
|
||||
$tagName = $buffer;
|
||||
$keys[] = $tagName;
|
||||
$buffer = "";
|
||||
break;
|
||||
case ' ':
|
||||
$state = static::OPTION_STATE_DEFAULT;
|
||||
$tagName = $buffer;
|
||||
$buffer = '';
|
||||
$keys[] = $tagName;
|
||||
break;
|
||||
|
||||
case null:
|
||||
$tagName = $buffer;
|
||||
$buffer = '';
|
||||
$keys[] = $tagName;
|
||||
break;
|
||||
default:
|
||||
$buffer .= $char;
|
||||
}
|
||||
break;
|
||||
|
||||
case static::OPTION_STATE_DEFAULT:
|
||||
switch($char){
|
||||
case ' ':
|
||||
// do nothing
|
||||
default:
|
||||
$state = static::OPTION_STATE_KEY;
|
||||
$buffer .= $char;
|
||||
}
|
||||
break;
|
||||
|
||||
case static::OPTION_STATE_VALUE:
|
||||
switch($char){
|
||||
case '"':
|
||||
$state = static::OPTION_STATE_QUOTED_VALUE;
|
||||
break;
|
||||
case null: // intentional fall-through
|
||||
case ' ': // key=value<space> delimits to next key
|
||||
$values[] = $buffer;
|
||||
$buffer = "";
|
||||
$state = static::OPTION_STATE_KEY;
|
||||
break;
|
||||
case ":":
|
||||
if($buffer=="javascript"){
|
||||
$state = static::OPTION_STATE_JAVASCRIPT;
|
||||
}
|
||||
$buffer .= $char;
|
||||
break;
|
||||
default:
|
||||
$buffer .= $char;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case static::OPTION_STATE_JAVASCRIPT:
|
||||
switch($char){
|
||||
case ";":
|
||||
$buffer .= $char;
|
||||
$values[] = $buffer;
|
||||
$buffer = "";
|
||||
$state = static::OPTION_STATE_KEY;
|
||||
|
||||
break;
|
||||
default:
|
||||
$buffer .= $char;
|
||||
}
|
||||
break;
|
||||
|
||||
case static::OPTION_STATE_KEY:
|
||||
switch($char){
|
||||
case '=':
|
||||
$state = static::OPTION_STATE_VALUE;
|
||||
$keys[] = $buffer;
|
||||
$buffer = '';
|
||||
break;
|
||||
case ' ': // ignore <space>key=value
|
||||
break;
|
||||
default:
|
||||
$buffer .= $char;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case static::OPTION_STATE_QUOTED_VALUE:
|
||||
switch($char){
|
||||
case null:
|
||||
case '"':
|
||||
$state = static::OPTION_STATE_KEY;
|
||||
$values[] = $buffer;
|
||||
$buffer = '';
|
||||
|
||||
// peek ahead. If the next character is not a space or a closing brace, we have a bad tag and need to abort
|
||||
if(isset($tagContent[$idx+1]) && $tagContent[$idx+1]!=" " && $tagContent[$idx+1]!="]" ){
|
||||
throw new ParserException("Badly formed attribute: $tagContent");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$buffer .= $char;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(!empty($char)){
|
||||
$state = static::OPTION_STATE_KEY;
|
||||
}
|
||||
|
||||
}
|
||||
if($idx >= $len){
|
||||
$done = true;
|
||||
}
|
||||
$idx++;
|
||||
}
|
||||
|
||||
if(count($keys) && count($values)){
|
||||
if(count($keys)==(count($values)+1)){
|
||||
array_unshift($values, "");
|
||||
}
|
||||
|
||||
$options = array_combine($keys, $values);
|
||||
}
|
||||
}
|
||||
catch(ParserException $e){
|
||||
// if we're in this state, then something evidently went wrong. We'll consider everything that came after the tagname to be the attribute for that keyname
|
||||
$options[$tagName]= substr($tagContent, strpos($tagContent, "=")+1);
|
||||
}
|
||||
return array($tagName, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the next step in parsing a tag. It's possible for it to still be invalid at this
|
||||
* point but many of the basic invalid tag name conditions have already been handled.
|
||||
*
|
||||
* @param ElementNode $parent the current parent element
|
||||
* @param Tokenizer $tokenizer the tokenizer we're using
|
||||
* @param string $tagContent the text between the [ and the ], assuming there is actually a ]
|
||||
*
|
||||
* @return ElementNode the new parent element
|
||||
*/
|
||||
protected function parseTag(ElementNode $parent, Tokenizer $tokenizer, $tagContent)
|
||||
{
|
||||
|
||||
$next;
|
||||
if (!$tokenizer->hasNext() || ($next = $tokenizer->next()) != ']') {
|
||||
/* This is a malformed tag. Both the previous [ and the tagContent
|
||||
* is really just plain text. */
|
||||
$this->createTextNode($parent, '[');
|
||||
$this->createTextNode($parent, $tagContent);
|
||||
return $parent;
|
||||
}
|
||||
|
||||
/* This is a well-formed tag consisting of [something] or [/something], but
|
||||
* we still need to ensure that 'something' is a valid tag name. Additionally,
|
||||
* if it's a closing tag, we need to ensure that there was a previous matching
|
||||
* opening tag.
|
||||
*/
|
||||
/* There could be attributes. */
|
||||
list($tmpTagName, $options) = $this->parseOptions($tagContent);
|
||||
|
||||
// $tagPieces = explode('=', $tagContent);
|
||||
// $tmpTagName = $tagPieces[0];
|
||||
|
||||
$actualTagName;
|
||||
if ('' != $tmpTagName && '/' == $tmpTagName[0]) {
|
||||
/* This is a closing tag name. */
|
||||
$actualTagName = substr($tmpTagName, 1);
|
||||
} else {
|
||||
$actualTagName = $tmpTagName;
|
||||
}
|
||||
|
||||
if ('' != $tmpTagName && '/' == $tmpTagName[0]) {
|
||||
/* This is attempting to close an open tag. We must verify that there exists an
|
||||
* open tag of the same type and that there is no option (options on closing
|
||||
* tags don't make any sense). */
|
||||
$elToClose = $parent->closestParentOfType($actualTagName);
|
||||
if (null == $elToClose || count($options) > 1) {
|
||||
/* Closing an unopened tag or has an option. Treat everything as plain text. */
|
||||
$this->createTextNode($parent, '[');
|
||||
$this->createTextNode($parent, $tagContent);
|
||||
$this->createTextNode($parent, ']');
|
||||
return $parent;
|
||||
} else {
|
||||
/* We're closing $elToClose. In order to do that, we just need to return
|
||||
* $elToClose's parent, since that will change our effective parent to be
|
||||
* elToClose's parent. */
|
||||
return $elToClose->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that this is a known bbcode tag name. */
|
||||
if ('' == $actualTagName || !$this->codeExists($actualTagName, !empty($options))) {
|
||||
/* This is an invalid tag name! Treat everything we've seen as plain text. */
|
||||
$this->createTextNode($parent, '[');
|
||||
$this->createTextNode($parent, $tagContent);
|
||||
$this->createTextNode($parent, ']');
|
||||
return $parent;
|
||||
}
|
||||
|
||||
/* If we're here, this is a valid opening tag. Let's make a new node for it. */
|
||||
$el = new ElementNode();
|
||||
$el->setNodeId(++$this->nextNodeid);
|
||||
$code = $this->getCode($actualTagName, !empty($options));
|
||||
$el->setCodeDefinition($code);
|
||||
if (!empty($options)) {
|
||||
/* We have an attribute we should save. */
|
||||
$el->setAttribute($options);
|
||||
}
|
||||
$parent->addChild($el);
|
||||
return $el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles parsing elements whose CodeDefinitions disable parsing of element
|
||||
* contents. This function uses a rolling window of 3 tokens until it finds the
|
||||
* appropriate closing tag or reaches the end of the token stream.
|
||||
*
|
||||
* @param ElementNode $parent the current parent element
|
||||
* @param Tokenizer $tokenizer the tokenizer we're using
|
||||
*
|
||||
* @return ElementNode the new parent element
|
||||
*/
|
||||
protected function parseAsTextUntilClose(ElementNode $parent, Tokenizer $tokenizer)
|
||||
{
|
||||
/* $parent's code definition doesn't allow its contents to be parsed. Here we use
|
||||
* a sliding window of three tokens until we find [ /tagname ], signifying the
|
||||
* end of the parent. */
|
||||
if (!$tokenizer->hasNext()) {
|
||||
return $parent;
|
||||
}
|
||||
$prevPrev = $tokenizer->next();
|
||||
if (!$tokenizer->hasNext()) {
|
||||
$this->createTextNode($parent, $prevPrev);
|
||||
return $parent;
|
||||
}
|
||||
$prev = $tokenizer->next();
|
||||
if (!$tokenizer->hasNext()) {
|
||||
$this->createTextNode($parent, $prevPrev);
|
||||
$this->createTextNode($parent, $prev);
|
||||
return $parent;
|
||||
}
|
||||
$curr = $tokenizer->next();
|
||||
while ('[' != $prevPrev || '/'.$parent->getTagName() != strtolower($prev) ||
|
||||
']' != $curr) {
|
||||
$this->createTextNode($parent, $prevPrev);
|
||||
$prevPrev = $prev;
|
||||
$prev = $curr;
|
||||
if (!$tokenizer->hasNext()) {
|
||||
$this->createTextNode($parent, $prevPrev);
|
||||
$this->createTextNode($parent, $prev);
|
||||
return $parent;
|
||||
}
|
||||
$curr = $tokenizer->next();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
7
vendor/jbbcode/jbbcode/JBBCode/ParserException.php
vendored
Normal file
7
vendor/jbbcode/jbbcode/JBBCode/ParserException.php
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
use Exception;
|
||||
|
||||
class ParserException extends Exception{
|
||||
}
|
||||
102
vendor/jbbcode/jbbcode/JBBCode/TextNode.php
vendored
Normal file
102
vendor/jbbcode/jbbcode/JBBCode/TextNode.php
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
require_once 'Node.php';
|
||||
|
||||
/**
|
||||
* Represents a piece of text data. TextNodes never have children.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class TextNode extends Node
|
||||
{
|
||||
/* The value of this text node */
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Constructs a text node from its text string
|
||||
*
|
||||
* @param string $val
|
||||
*/
|
||||
public function __construct($val)
|
||||
{
|
||||
$this->value = $val;
|
||||
}
|
||||
|
||||
public function accept(NodeVisitor $visitor)
|
||||
{
|
||||
$visitor->visitTextNode($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.Node::isTextNode()
|
||||
*
|
||||
* returns true
|
||||
*/
|
||||
public function isTextNode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text string value of this text node.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.Node::getAsText()
|
||||
*
|
||||
* Returns the text representation of this node.
|
||||
*
|
||||
* @return this node represented as text
|
||||
*/
|
||||
public function getAsText()
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.Node::getAsBBCode()
|
||||
*
|
||||
* Returns the bbcode representation of this node. (Just its value)
|
||||
*
|
||||
* @return this node represented as bbcode
|
||||
*/
|
||||
public function getAsBBCode()
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see JBBCode.Node::getAsHTML()
|
||||
*
|
||||
* Returns the html representation of this node. (Just its value)
|
||||
*
|
||||
* @return this node represented as HTML
|
||||
*/
|
||||
public function getAsHTML()
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the text value contained within this text node.
|
||||
*
|
||||
* @param newValue the new text value of the text node
|
||||
*/
|
||||
public function setValue($newValue)
|
||||
{
|
||||
$this->value = $newValue;
|
||||
}
|
||||
|
||||
}
|
||||
105
vendor/jbbcode/jbbcode/JBBCode/Tokenizer.php
vendored
Normal file
105
vendor/jbbcode/jbbcode/JBBCode/Tokenizer.php
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace JBBCode;
|
||||
|
||||
/**
|
||||
* This Tokenizer is used while constructing the parse tree. The tokenizer
|
||||
* handles splitting the input into brackets and miscellaneous text. The
|
||||
* parser is then built as a FSM ontop of these possible inputs.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class Tokenizer
|
||||
{
|
||||
|
||||
protected $tokens = array();
|
||||
protected $i = -1;
|
||||
|
||||
/**
|
||||
* Constructs a tokenizer from the given string. The string will be tokenized
|
||||
* upon construction.
|
||||
*
|
||||
* @param $str the string to tokenize
|
||||
*/
|
||||
public function __construct($str)
|
||||
{
|
||||
$strStart = 0;
|
||||
for ($index = 0; $index < strlen($str); ++$index) {
|
||||
if (']' == $str[$index] || '[' == $str[$index]) {
|
||||
/* Are there characters in the buffer from a previous string? */
|
||||
if ($strStart < $index) {
|
||||
array_push($this->tokens, substr($str, $strStart, $index - $strStart));
|
||||
$strStart = $index;
|
||||
}
|
||||
|
||||
/* Add the [ or ] to the tokens array. */
|
||||
array_push($this->tokens, $str[$index]);
|
||||
$strStart = $index+1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($strStart < strlen($str)) {
|
||||
/* There are still characters in the buffer. Add them to the tokens. */
|
||||
array_push($this->tokens, substr($str, $strStart, strlen($str) - $strStart));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is another token in the token stream.
|
||||
*/
|
||||
public function hasNext()
|
||||
{
|
||||
return count($this->tokens) > 1 + $this->i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the token stream to the next token and returns the new token.
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if (!$this->hasNext()) {
|
||||
return null;
|
||||
} else {
|
||||
return $this->tokens[++$this->i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current token.
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
if ($this->i < 0) {
|
||||
return null;
|
||||
} else {
|
||||
return $this->tokens[$this->i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the token stream back a token.
|
||||
*/
|
||||
public function stepBack()
|
||||
{
|
||||
if ($this->i > -1) {
|
||||
$this->i--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the tokenizer, returning to the beginning of the token stream.
|
||||
*/
|
||||
public function restart()
|
||||
{
|
||||
$this->i = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* toString method that returns the entire string from the current index on.
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
return implode('', array_slice($this->tokens, $this->i + 1));
|
||||
}
|
||||
|
||||
}
|
||||
12
vendor/jbbcode/jbbcode/JBBCode/examples/1-GettingStarted.php
vendored
Normal file
12
vendor/jbbcode/jbbcode/JBBCode/examples/1-GettingStarted.php
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
require_once "/path/to/jbbcode/Parser.php";
|
||||
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
|
||||
$text = "The default codes include: [b]bold[/b], [i]italics[/i], [u]underlining[/u], ";
|
||||
$text .= "[url=http://jbbcode.com]links[/url], [color=red]color![/color] and more.";
|
||||
|
||||
$parser->parse($text);
|
||||
|
||||
print $parser->getAsHtml();
|
||||
10
vendor/jbbcode/jbbcode/JBBCode/examples/2-ClosingUnclosedTags.php
vendored
Normal file
10
vendor/jbbcode/jbbcode/JBBCode/examples/2-ClosingUnclosedTags.php
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
require_once "/path/to/jbbcode/Parser.php";
|
||||
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
|
||||
$text = "The bbcode in here [b]is never closed!";
|
||||
$parser->parse($text);
|
||||
|
||||
print $parser->getAsBBCode();
|
||||
11
vendor/jbbcode/jbbcode/JBBCode/examples/3-MarkuplessText.php
vendored
Normal file
11
vendor/jbbcode/jbbcode/JBBCode/examples/3-MarkuplessText.php
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
require_once "/path/to/jbbcode/Parser.php";
|
||||
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
|
||||
$text = "[b][u]There is [i]a lot[/i] of [url=http://en.wikipedia.org/wiki/Markup_language]markup[/url] in this";
|
||||
$text .= "[color=#333333]text[/color]![/u][/b]";
|
||||
$parser->parse($text);
|
||||
|
||||
print $parser->getAsText();
|
||||
7
vendor/jbbcode/jbbcode/JBBCode/examples/4-CreatingNewCodes.php
vendored
Normal file
7
vendor/jbbcode/jbbcode/JBBCode/examples/4-CreatingNewCodes.php
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
require_once "/path/to/jbbcode/Parser.php";
|
||||
|
||||
$parser = new JBBCode\Parser();
|
||||
|
||||
$parser->addBBCode("quote", '<div class="quote">{param}</div>');
|
||||
$parser->addBBCode("code", '<pre class="code">{param}</pre>', false, false, 1);
|
||||
22
vendor/jbbcode/jbbcode/JBBCode/examples/SmileyVisitorTest.php
vendored
Normal file
22
vendor/jbbcode/jbbcode/JBBCode/examples/SmileyVisitorTest.php
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
require_once("../Parser.php");
|
||||
require_once("../visitors/SmileyVisitor.php");
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
|
||||
if (count($argv) < 2) {
|
||||
die("Usage: " . $argv[0] . " \"bbcode string\"\n");
|
||||
}
|
||||
|
||||
$inputText = $argv[1];
|
||||
|
||||
$parser->parse($inputText);
|
||||
|
||||
$smileyVisitor = new \JBBCode\visitors\SmileyVisitor();
|
||||
$parser->accept($smileyVisitor);
|
||||
|
||||
echo $parser->getAsHTML() . "\n";
|
||||
23
vendor/jbbcode/jbbcode/JBBCode/examples/TagCountingVisitorTest.php
vendored
Normal file
23
vendor/jbbcode/jbbcode/JBBCode/examples/TagCountingVisitorTest.php
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
require_once("../Parser.php");
|
||||
require_once("../visitors/TagCountingVisitor.php");
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
|
||||
if (count($argv) < 3) {
|
||||
die("Usage: " . $argv[0] . " \"bbcode string\" <tag name to check>\n");
|
||||
}
|
||||
|
||||
$inputText = $argv[1];
|
||||
$tagName = $argv[2];
|
||||
|
||||
$parser->parse($inputText);
|
||||
|
||||
$tagCountingVisitor = new \JBBCode\visitors\TagCountingVisitor();
|
||||
$parser->accept($tagCountingVisitor);
|
||||
|
||||
echo $tagCountingVisitor->getFrequency($tagName) . "\n";
|
||||
85
vendor/jbbcode/jbbcode/JBBCode/tests/BBCodeToBBCodeTest.php
vendored
Normal file
85
vendor/jbbcode/jbbcode/JBBCode/tests/BBCodeToBBCodeTest.php
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
|
||||
|
||||
/**
|
||||
* Test cases testing the functionality of parsing bbcode and
|
||||
* retrieving a bbcode well-formed bbcode representation.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class BBCodeToBBCodeTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* A utility method for these tests that will evaluate its arguments as bbcode with
|
||||
* a fresh parser loaded with only the default bbcodes. It returns the
|
||||
* bbcode output, which in most cases should be in the input itself.
|
||||
*/
|
||||
private function defaultBBCodeParse($bbcode)
|
||||
{
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
$parser->parse($bbcode);
|
||||
return $parser->getAsBBCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given bbcode matches the given text when
|
||||
* the bbcode is run through defaultBBCodeParse
|
||||
*/
|
||||
private function assertBBCodeOutput($bbcode, $text)
|
||||
{
|
||||
$this->assertEquals($this->defaultBBCodeParse($bbcode), $text);
|
||||
}
|
||||
|
||||
public function testEmptyString()
|
||||
{
|
||||
$this->assertBBCodeOutput('', '');
|
||||
}
|
||||
|
||||
public function testOneTag()
|
||||
{
|
||||
$this->assertBBCodeOutput('[b]this is bold[/b]', '[b]this is bold[/b]');
|
||||
}
|
||||
|
||||
public function testOneTagWithSurroundingText()
|
||||
{
|
||||
$this->assertBBCodeOutput('buffer text [b]this is bold[/b] buffer text',
|
||||
'buffer text [b]this is bold[/b] buffer text');
|
||||
}
|
||||
|
||||
public function testMultipleTags()
|
||||
{
|
||||
$bbcode = 'this is some text with [b]bold tags[/b] and [i]italics[/i] and ' .
|
||||
'things like [u]that[/u].';
|
||||
$bbcodeOutput = 'this is some text with [b]bold tags[/b] and [i]italics[/i] and ' .
|
||||
'things like [u]that[/u].';
|
||||
$this->assertBBCodeOutput($bbcode, $bbcodeOutput);
|
||||
}
|
||||
|
||||
public function testCodeOptions()
|
||||
{
|
||||
$code = 'This contains a [url=http://jbbcode.com]url[/url] which uses an option.';
|
||||
$codeOutput = 'This contains a [url=http://jbbcode.com]url[/url] which uses an option.';
|
||||
$this->assertBBCodeOutput($code, $codeOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCodeOptions
|
||||
*/
|
||||
public function testOmittedOption()
|
||||
{
|
||||
$code = 'This doesn\'t use the url option [url]http://jbbcode.com[/url].';
|
||||
$codeOutput = 'This doesn\'t use the url option [url]http://jbbcode.com[/url].';
|
||||
$this->assertBBCodeOutput($code, $codeOutput);
|
||||
}
|
||||
|
||||
public function testUnclosedTags()
|
||||
{
|
||||
$code = '[b]bold';
|
||||
$codeOutput = '[b]bold[/b]';
|
||||
$this->assertBBCodeOutput($code, $codeOutput);
|
||||
}
|
||||
|
||||
}
|
||||
78
vendor/jbbcode/jbbcode/JBBCode/tests/BBCodeToTextTest.php
vendored
Normal file
78
vendor/jbbcode/jbbcode/JBBCode/tests/BBCodeToTextTest.php
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
|
||||
|
||||
/**
|
||||
* Test cases testing the ability to parse bbcode and retrieve a
|
||||
* plain text representation without any markup.
|
||||
*
|
||||
* @author jbowens
|
||||
*/
|
||||
class BBCodeToTextTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* A utility method for these tests that will evaluate
|
||||
* its arguments as bbcode with a fresh parser loaded
|
||||
* with only the default bbcodes. It returns the
|
||||
* text output.
|
||||
*/
|
||||
private function defaultTextParse($bbcode)
|
||||
{
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
$parser->parse($bbcode);
|
||||
return $parser->getAsText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given bbcode matches the given text when
|
||||
* the bbcode is run through defaultTextParse
|
||||
*/
|
||||
private function assertTextOutput($bbcode, $text)
|
||||
{
|
||||
$this->assertEquals($text, $this->defaultTextParse($bbcode));
|
||||
}
|
||||
|
||||
public function testEmptyString()
|
||||
{
|
||||
$this->assertTextOutput('', '');
|
||||
}
|
||||
|
||||
public function testOneTag()
|
||||
{
|
||||
$this->assertTextOutput('[b]this is bold[/b]', 'this is bold');
|
||||
}
|
||||
|
||||
public function testOneTagWithSurroundingText()
|
||||
{
|
||||
$this->assertTextOutput('buffer text [b]this is bold[/b] buffer text',
|
||||
'buffer text this is bold buffer text');
|
||||
}
|
||||
|
||||
public function testMultipleTags()
|
||||
{
|
||||
$bbcode = 'this is some text with [b]bold tags[/b] and [i]italics[/i] and ' .
|
||||
'things like [u]that[/u].';
|
||||
$text = 'this is some text with bold tags and italics and things like that.';
|
||||
$this->assertTextOutput($bbcode, $text);
|
||||
}
|
||||
|
||||
public function testCodeOptions()
|
||||
{
|
||||
$code = 'This contains a [url=http://jbbcode.com]url[/url] which uses an option.';
|
||||
$text = 'This contains a url which uses an option.';
|
||||
$this->assertTextOutput($code, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCodeOptions
|
||||
*/
|
||||
public function testOmittedOption()
|
||||
{
|
||||
$code = 'This doesn\'t use the url option [url]http://jbbcode.com[/url].';
|
||||
$text = 'This doesn\'t use the url option http://jbbcode.com.';
|
||||
$this->assertTextOutput($code, $text);
|
||||
}
|
||||
|
||||
}
|
||||
54
vendor/jbbcode/jbbcode/JBBCode/tests/DefaultCodesTest.php
vendored
Normal file
54
vendor/jbbcode/jbbcode/JBBCode/tests/DefaultCodesTest.php
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
|
||||
|
||||
/**
|
||||
* Test cases for the default bbcode set.
|
||||
*
|
||||
* @author jbowens
|
||||
* @since May 2013
|
||||
*/
|
||||
class DefaultCodesTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Asserts that the given bbcode string produces the given html string
|
||||
* when parsed with the default bbcodes.
|
||||
*/
|
||||
public function assertProduces($bbcode, $html)
|
||||
{
|
||||
$parser = new \JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
$parser->parse($bbcode);
|
||||
$this->assertEquals($html, $parser->getAsHtml());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the [b] bbcode.
|
||||
*/
|
||||
public function testBold()
|
||||
{
|
||||
$this->assertProduces('[b]this should be bold[/b]', '<strong>this should be bold</strong>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the [color] bbcode.
|
||||
*/
|
||||
public function testColor()
|
||||
{
|
||||
$this->assertProduces('[color=red]red[/color]', '<span style="color: red">red</span>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the example from the documentation.
|
||||
*/
|
||||
public function testExample()
|
||||
{
|
||||
$text = "The default codes include: [b]bold[/b], [i]italics[/i], [u]underlining[/u], ";
|
||||
$text .= "[url=http://jbbcode.com]links[/url], [color=red]color![/color] and more.";
|
||||
$html = 'The default codes include: <strong>bold</strong>, <em>italics</em>, <u>underlining</u>, ';
|
||||
$html .= '<a href="http://jbbcode.com">links</a>, <span style="color: red">color!</span> and more.';
|
||||
$this->assertProduces($text, $html);
|
||||
}
|
||||
|
||||
}
|
||||
77
vendor/jbbcode/jbbcode/JBBCode/tests/HTMLSafeTest.php
vendored
Normal file
77
vendor/jbbcode/jbbcode/JBBCode/tests/HTMLSafeTest.php
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
|
||||
|
||||
/**
|
||||
* Test cases testing the HTMLSafe visitor, which escapes all html characters in the source text
|
||||
*
|
||||
* @author astax-t
|
||||
*/
|
||||
class HTMLSafeTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Asserts that the given bbcode string produces the given html string
|
||||
* when parsed with the default bbcodes.
|
||||
*/
|
||||
public function assertProduces($bbcode, $html)
|
||||
{
|
||||
$parser = new \JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
$parser->parse($bbcode);
|
||||
|
||||
$htmlsafer = new JBBCode\visitors\HTMLSafeVisitor();
|
||||
$parser->accept($htmlsafer);
|
||||
|
||||
$this->assertEquals($html, $parser->getAsHtml());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests escaping quotes and ampersands in simple text
|
||||
*/
|
||||
public function testQuoteAndAmp()
|
||||
{
|
||||
$this->assertProduces('te"xt te&xt', 'te"xt te&xt');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests escaping quotes and ampersands inside a BBCode tag
|
||||
*/
|
||||
public function testQuoteAndAmpInTag()
|
||||
{
|
||||
$this->assertProduces('[b]te"xt te&xt[/b]', '<strong>te"xt te&xt</strong>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests escaping HTML tags
|
||||
*/
|
||||
public function testHtmlTag()
|
||||
{
|
||||
$this->assertProduces('<b>not bold</b>', '<b>not bold</b>');
|
||||
$this->assertProduces('[b]<b>bold</b>[/b] <hr>', '<strong><b>bold</b></strong> <hr>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests escaping ampersands in URL using [url]...[/url]
|
||||
*/
|
||||
public function testUrlParam()
|
||||
{
|
||||
$this->assertProduces('text [url]http://example.com/?a=b&c=d[/url] more text', 'text <a href="http://example.com/?a=b&c=d">http://example.com/?a=b&c=d</a> more text');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests escaping ampersands in URL using [url=...] tag
|
||||
*/
|
||||
public function testUrlOption()
|
||||
{
|
||||
$this->assertProduces('text [url=http://example.com/?a=b&c=d]this is a "link"[/url]', 'text <a href="http://example.com/?a=b&c=d">this is a "link"</a>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests escaping ampersands in URL using [url=...] tag when URL is in quotes
|
||||
*/
|
||||
public function testUrlOptionQuotes()
|
||||
{
|
||||
$this->assertProduces('text [url="http://example.com/?a=b&c=d"]this is a "link"[/url]', 'text <a href="http://example.com/?a=b&c=d">this is a "link"</a>');
|
||||
}
|
||||
|
||||
}
|
||||
46
vendor/jbbcode/jbbcode/JBBCode/tests/NestLimitTest.php
vendored
Normal file
46
vendor/jbbcode/jbbcode/JBBCode/tests/NestLimitTest.php
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
|
||||
|
||||
/**
|
||||
* Test cases for CodeDefinition nest limits. If an element is nested beyond
|
||||
* its CodeDefinition's nest limit, it should be removed from the parse tree.
|
||||
*
|
||||
* @author jbowens
|
||||
* @since May 2013
|
||||
*/
|
||||
class NestLimitTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests that when elements have no nest limits they may be
|
||||
* nested indefinitely.
|
||||
*/
|
||||
public function testIndefiniteNesting()
|
||||
{
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addBBCode('b', '<strong>{param}</strong>', false, true, -1);
|
||||
$parser->parse('[b][b][b][b][b][b][b][b]bold text[/b][/b][/b][/b][/b][/b][/b][/b]');
|
||||
$this->assertEquals('<strong><strong><strong><strong><strong><strong><strong><strong>' .
|
||||
'bold text' .
|
||||
'</strong></strong></strong></strong></strong></strong></strong></strong>',
|
||||
$parser->getAsHtml());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test over nesting.
|
||||
*/
|
||||
public function testOverNesting()
|
||||
{
|
||||
$parser = new JBBCode\Parser();
|
||||
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
|
||||
$parser->addBBCode('quote', '<blockquote>{param}</blockquote>', false, true, 2);
|
||||
$bbcode = '[quote][quote][quote]wut[/quote] huh?[/quote] i don\'t know[/quote]';
|
||||
$parser->parse($bbcode);
|
||||
$expectedBbcode = '[quote][quote] huh?[/quote] i don\'t know[/quote]';
|
||||
$expectedHtml = '<blockquote><blockquote> huh?</blockquote> i don\'t know</blockquote>';
|
||||
$this->assertEquals($expectedBbcode, $parser->getAsBBCode());
|
||||
$this->assertEquals($expectedHtml, $parser->getAsHtml());
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue